Tags are just a list of unique strings.
Front : I use Select2
, there is a really good tag feature : http://ivaynberg.github.io/select2/. It will take/return a string to the server with each "tag" separated by a comma : tag1,tag2,tag3
. You can also configure a web-service to research existing tags.
Back : I create a DataTransformer (http://symfony.com/doc/current/cookbook/form/data_transformers.html) as a service and i inject the entity manager in it :
class TagsTransformer implements DataTransformerInterface
{
private $em;
/**
* @param EntityManager $em
*/
public function __construct(EntityManager $em)
{
$this->em = $em;
}
public function transform($value)
{
if (null === $value) {
return '';
}
if ($value instanceof Collection) {
return implode(',', array_map(function (Tag $tag) {
return (string)$tag;
}, $value->toArray()));
}
return $value;
}
public function reverseTransform($value)
{
if (empty($value)) {
return null;
}
if (is_string($value)) {
$values = explode(',', $value);
foreach ($values as &$value) {
// Find or create it (create the method)
$value = $this->em->getRepository('MySuperBundle:Tag')->findOrCreate(trim($value));
}
unset($value);
return $values;
}
return $value;
}
}
The goal of this transformer is to :
- Transform : take the ArrayCollection of Tags entity from Doctrine, and convert it as a simple comma separated string
- Reverse : take a simple comma separated string and convert it as an array of unique Tag entity
We then create a Form for tags (again, as a service, with the data transformer in it) :
class TagsType extends AbstractType
{
private $tagsTransformer;
/**
* @param TagsTransformer $tagsTransformer
*/
public function __construct(TagsTransformer $tagsTransformer)
{
$this->tagsTransformer = $tagsTransformer;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->addModelTransformer($this->tagsTransformer);
}
public function getParent()
{
return 'text';
}
}
Finally, in your form (blog post form for example), you'll have to use your TagsType
new "field".