duanpeng1532 2014-12-28 22:51
浏览 64
已采纳

将表单的文本字段映射到实体的ArrayCollection

I am using tags on a form using tagsinput :

enter image description here

This plugin ends-up with a single text field containing tags separated by a comma (eg: tag1,tag2,...)

Those tags are currently managed on a non-mapped form field:

    $builder
       // ...
       ->add('tags', 'text', array(
               'mapped' => false,
               'required' => false,
       ))
    ;

And finally, they are stored on an ArrayCollection, as this is a bad practice to store multiple values in a database field:

/**
 * @var ArrayCollection[FiddleTag]
 *
 * @ORM\OneToMany(targetEntity="FiddleTag", mappedBy="fiddle", cascade={"all"}, orphanRemoval=true)
 */
protected $tags;

To map my form to my entity, I can do some code in my controller like this:

    $data->clearTags();
    foreach (explode(',', $form->get('tags')->getData()) as $tag)
    {
        $fiddleTag = new FiddleTag();
        $fiddleTag->setTag($tag);
        $data->addTag($fiddleTag);
    }

But this looks the wrong way at first sight.

I am wondering what is the best practice to map my entity to my form, and my form to my entity.

  • 写回答

1条回答 默认 最新

  • duanfu3634 2014-12-29 01:56
    关注

    This is tricky since you aren't just embedding a collection of Tag forms that are say, all separate text fields. I suppose you could do that with some trickery, but what about using a data transformer instead? You could convert a comma-separated list of tags to an ArrayCollection and pass that back to the form, and on the flip-side, take the collection and return the tags as a comma-separated string.

    Data transformer

    <kbd>FiddleTagsTransformer.php</kbd>

    <?php
    
    namespace Fuz\AppBundle\Transformer;
    
    use Doctrine\Common\Collections\ArrayCollection;
    use Symfony\Component\Form\DataTransformerInterface;
    use Fuz\AppBundle\Entity\FiddleTag;
    
    class FiddleTagTransformer implements DataTransformerInterface
    {
    
        public function transform($tagCollection)
        {
            $tags = array();
    
            foreach ($tagCollection as $fiddleTag)
            {
                $tags[] = $fiddleTag->getTag();
            }
    
            return implode(',', $tags);
        }
    
        public function reverseTransform($tags)
        {
            $tagCollection = new ArrayCollection();
    
            foreach (explode(',', $tags) as $tag)
            {
                $fiddleTag = new FiddleTag();
                $fiddleTag->setTag($tag);
                $tagCollection->add($fiddleTag);
            }
    
            return $tagCollection;
        }
    
    }
    

    Note: you cannot specify ArrayCollection type to public function transform($tagCollection) because your implementation should match the interface.

    Form type

    The second step is to replace your form field declaration so it will use the data transformer transparently, you'll not even need to do anything in your controller:

    <kbd>FiddleType.php</kbd>

    $builder
       // ...
       ->add(
            $builder
                ->create('tags', 'text', array(
                        'required' => false,
                ))
                ->addModelTransformer(new FiddleTagTransformer())
       )
    ;
    

    Validation

    You can use @Assert\Count to limit the number of allowed tags, and @Assert\Valid if your FiddleTag entity has some validation constraints itself.

    <kbd>Fiddle.php</kbd>

    /**
     * @var ArrayCollection[FiddleTag]
     *
     * @ORM\OneToMany(targetEntity="FiddleTag", mappedBy="fiddle", cascade={"all"}, orphanRemoval=true)
     * @Assert\Count(max = 5, maxMessage = "You can't set more than 5 tags.")
     * @Assert\Valid()
     */
    protected $tags;
    

    Further reading

    See the Symfony2 doc about data transformers: http://symfony.com/doc/current/cookbook/form/data_transformers.html

    See these posts for some other ideas:

    Parsing comma separated string into multiple database entries (eg. Tags)

    How does Symfony 2 find custom form types?

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 基于卷积神经网络的声纹识别
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 stm32开发clion时遇到的编译问题