Setting up Form Collection for Tags in Symfony

This is the second article in a series on setting up a ManyToMany association for tags in Symfony. You can read the previous article where we created our Product and Tag entities here:

  1. Managing Tags in ManyToMany association with Symfony

Now that our entities have been created, it’s time to create our forms. Basically, what we want here is a Product submission form where you can add/remove a collection of Tags which will also be associated to our Product. First, let’s create a Tag form which will be added to our Product form later to collect tags.

We only need a 'name'  for each tag.

Next, we’ll create the Product form:

We add 'tags'  here to the builder as a CollectionType , and set 'entry_type'  to TagType::class . That is the TagType form class we created above in TagType.php, with ::class to get the fully qualified class name.

We set  'allow_add'  and 'allow_delete'  to  true  because we want to be able to add and delete the associations of Tags to each Product.

Finally, I set 'required' => false , because I want adding Tags to be optional.

We haven’t gotten to the point of setting up anything in our Controller or templates yet, but I want to show you what happens now if we leave things the way they are so far in this example.

Currently, if you added one Product (BMW) with the following tags:

new product BMW

When you check your database, you would see this in your tables:

product

Product table

product_tag

product_tag table

tag:

tag table

Great. Now imagine adding another Product (Honda) with a car tag again, and see what happens:

add product Honda

Check your tables and you will find:

product

product table 2

product_tag

product_tag table 2

tag

tag table 2

As you can see, it is adding duplicate Tags to our tables. However, rather than adding an unnecessary duplicate car tag (tag.id: 3), we want the Honda (product.id: 2) to be associated to the original car tag (tag.id: 1) in the product_tag table. So how can we accomplish this?

The method which I decided on was to setup a Data Transformer which checks if a tag already exists in the database. If so, it replaces the tag submitted by the form with the one already in the database. This way, the Product will be associated with the original tag in the database, and no new duplicate tag will be added.

I cover this in the next article: Using a Data Transformer in Symfony to handle duplicate tags