具有EntityType下拉值的Bootstrap TagsInput(Symfony)

时间:2019-06-22 16:20:13

标签: forms doctrine-orm symfony4 bootstrap-tags-input

我正在制作一张表格来注册书籍(Symfony 4),每本书都有一个独特的出版商(ManyToOne)和一个或多个作者(ManyToMany)。这两个字段都用 Bootstrap TagsInput 作为标签填写在表单中,因此,如果用户在这些字段中键入内容,它们将建议数据库表中的值列表,否则,将建议新值提交时将与其他图书数据一起插入。

我遵循了Symfony网站上“最佳做法”的官方示例,并且标记系统适用于作者,因为它是CollectionType,但不适用于发布者,因为这是一个EntityType。我该如何适应呢?无法将发布者的值转换成逗号分隔的字符串,以便TagInput可以识别它。

图书实体(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'
        ))
    }
}

AuthorType

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 } }) }}

这是我用于编辑者和作者的代码,因此您可以比较一个有效的代码和一个无效的代码。它们并没有什么不同,但是有些地方出了问题,我也不知道这是什么,或者我需要更改什么。

1 个答案:

答案 0 :(得分:0)

好的,我找到了解决方案。我已经在两个Transformers中进行了所有更改,因为问题是我将实体转换成的格式,反之亦然。