【发布时间】:2019-06-22 16:20:13
【问题描述】:
我正在制作一个表格来注册图书 (Symfony 4),每个图书都有一个唯一的出版商 (ManyToOne) 和一个或多个作者 (ManyToMany)。这两个字段都作为标签填写在表单中,使用 Bootstrap TagsInput,因此如果用户在这些字段中输入,他们将建议数据库表中的值列表,如果没有,则建议新值将在提交时与其他图书数据一起插入。
我遵循了 Symfony 网站上最佳实践的官方示例,标签系统适用于作者,因为它是 CollectionType,但不适用于出版商,因为它是一个实体类型。我怎么能适应它?无法将发布者值转换为逗号分隔的字符串,以便 TagsInput 可以识别。
图书实体(App\Entity\Book.php)
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
class Book
{
/**
* @var \Publisher
*
* @ORM\ManyToOne(targetEntity="Publisher", cascade={"persist"})
* @ORM\JoinColumns({
* @ORM\JoinColumn(nullable=false, name="publisher_id", referencedColumnName="id")
* })
*/
private $publisher;
/**
* @var Author[]|ArrayCollection
*
* @ORM\ManyToMany(targetEntity="Author", cascade={"persist"})
* @ORM\JoinTable(name="authors_books")
*/
private $authors;
public function __construct()
{
$this->authors = new ArrayCollection();
}
public function getPublisher()
{
return $this->publisher;
}
public function getAuthors(): Collection
{
return $this->authors;
}
}
图书表单(App\Form\BookType.php)
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use App\Form\Type\PublisherType;
use App\Form\Type\AuthorType;
class BookType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options){
$builder
->add('publisher', PublisherType::class, array(
'label' => 'Publisher',
))
->add('authors', AuthorType::class, array(
'label' => 'Author/s'
))
}
}
作者类型
namespace App\Form\Type;
use Symfony\Bridge\Doctrine\Form\DataTransformer\CollectionToArrayTransformer;
use App\Form\DataTransformer\AuthorToStringTransformer;
use App\Repository\AuthorRepository;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
class AuthorType extends AbstractType {
private $authors;
public function __construct(AuthorRepository $authors_repo)
{
$this->authors = $authors_repo;
}
public function buildForm(FormBuilderInterface $builder, array $options){
$builder
->addModelTransformer(new CollectionToArrayTransformer(), true)
->addModelTransformer(new AuthorToStringTransformer($this->authors), true)
;
}
public function buildView(FormView $view, FormInterface $form, array $options): void
{
$view->vars['authors'] = $this->authors->findAll();
}
public function getParent()
{
return TextType::class;
}
}
PublisherType
namespace App\Form\Type;
use App\Form\DataTransformer\EntityToArrayTransformer;
use App\Form\DataTransformer\PublisherToStringTransformer;
use App\Repository\PublisherRepository;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
class PublisherType extends AbstractType {
private $publishers;
public function __construct(PublisherRepository $publisher_repo) {
$this->publishers = $publisher_repo;
}
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->addModelTransformer(new EntityToArrayTransformer(), true)
->addModelTransformer(new PublisherToStringTransformer($this->publishers), true);
}
public function buildView(FormView $view, FormInterface $form, array $options): void
{
$publishers = $this->publishers->findAll();
}
public function getParent()
{
return TextType::class;
}
}
CollectionToArrayTransformer
namespace Symfony\Bridge\Doctrine\Form\DataTransformer;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Symfony\Component\Form\DataTransformerInterface;
class CollectionToArrayTransformer implements DataTransformerInterface
{
public function transform($collection)
{
if (null === $collection) {
return [];
}
if (\is_array($collection)) {
return $collection;
}
return $collection->toArray();
}
}
EnityToArrayTransformer
namespace App\Form\DataTransformer;
use Symfony\Component\Form\DataTransformerInterface;
class EntityToArrayTransformer implements DataTransformerInterface
{
public function transform($entity)
{
if (null === $entity) {
return [];
}
return [$entity];
}
}
AuthorToStringTransformer
namespace App\Form\DataTransformer;
use App\Entity\Author;
use App\Repository\AuthorRepository;
use Symfony\Component\Form\DataTransformerInterface;
class AuthorToStringTransformer implements DataTransformerInterface
{
private $authors;
public function __construct(AuthorRepository $authors)
{
$this->authors = $authors;
}
public function transform($authors): string
{
/* @var Author[] $authors */
return implode(',', $authors);
}
public function reverseTransform($string): array
{
...
}
}
PublisherToStringTransformer
namespace App\Form\DataTransformer;
use App\Entity\Publisher;
use App\Repository\PublisherRepository;
use Symfony\Component\Form\DataTransformerInterface;
class PublisherToStringTransformer implements DataTransformerInterface
{
private $publishers;
public function __construct(PublisherRepository $publishers)
{
$this->publishers = $publishers;
}
public function transform($publisher): string
{
/* @var Publisher[] $publisher */
return implode(',', $publisher);
}
public function reverseTransform($publisher): string
{
...
}
}
表格树枝
{{ form_widget(form.publisher, {'attr': {'class': class, 'data-toggle': 'tagsinput', 'data-publishers': form.publisher.vars.publishers|json_encode } }) }}
{{ form_widget(form.publisher, {'attr': {'class': class, 'data-toggle': 'tagsinput', 'data-authors': form.publisher.vars.authors|json_encode } }) }}
这是我用于编辑和作者的代码,以便您可以比较一个有效和一个无效。它们并没有太大的不同,但有些地方出了问题,我不知道它是什么或我需要改变什么。
【问题讨论】:
标签: forms doctrine-orm symfony4 bootstrap-tags-input