Display form text field for ArrayCollection

I use tags in the form using tagsinput :

enter image description here

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

Currently, these tags are managed in the form field without displaying:

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

And finally, they are stored on an ArrayCollection, since it 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 display my form in my entity, I can make the code in my controller as follows:

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

But at first glance it does not look like that.

I am wondering what is the best way to map my essence into my form and my form for my essence.

+5
source share
1 answer

This is difficult because you are not just embedding a collection of tag forms that, say, are all separate text fields. I suppose you could do this with some tricks, but what about using a data transformer? You can convert the list of tags with comma-delimited tags to ArrayCollection and pass them back to the form, and on the flip side, take a collection and return the tags as a split comma string.

Data transformer

FiddleTagsTransformer.php

 <?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 an ArrayCollection type for public function transform($tagCollection) because your implementation must conform to the interface.

Type of form

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

FiddleType.php

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

Check

You can use @Assert \ Count to limit the number of allowed tags and @Assert \ Valid if your FiddleTag object has some validation restrictions.

Fiddle.php

 /** * @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 document on data transformers: http://symfony.com/doc/current/cookbook/form/data_transformers.html

See these posts for some other ideas:

Separating comma-separated strings into multiple records in the database (e.g. tags)

How does symfony 2 find custom form types?

+9
source

Source: https://habr.com/ru/post/1210011/


All Articles