【问题标题】:Bootstrap TagsInput with EntityType dropdown values (Symfony)带有 EntityType 下拉值的引导标签输入 (Symfony)
【发布时间】: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


    【解决方案1】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-13
      • 2017-06-24
      • 2016-03-13
      • 2013-02-09
      • 2015-11-10
      • 1970-01-01
      相关资源
      最近更新 更多