Learn how to retrieve the entity object of every option inside a EntityType field with Twig in your Symfony form.

In most of the cases, tables without foreign relations in a database is far from the reality. This means that you will have always at least one foreign relation from a table to another, ignoring the type of project. In the Many-To-Many Relationship, implemented with Doctrine in your Symfony project can be a headache, however if you have discovered how to implement correctly, you surely have an EntityType field in your form. For this article we'll create a simple example with the relationship Games to Categories, in this case every Game can be related to many Categories, which means that in our Games form, we'll give the user the possibility to choose to which categories is the game related, therefore our Entity Field will be rendered as multiple checkbox and obviously multiple selections are allowed:

<?php

namespace AppBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Form\FormInterface;

// Add reference to the Categories Entity and EntityType field
use AppBundle\Entity\Categories;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;

class GamesType extends AbstractType
{
    // ... //

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        // ... //

        // Add the field "Categories" to the GamesForm
        $form->add('Categories', EntityType::class, [
            // Multiple selection allowed
            'multiple' => true,
            // Render as checkboxes
            'expanded' => true,
            // This field shows all the categories
            'class'    => Categories::class,
            'mapped' => false
        ]);
        // ... //
    }
     
    // ... //
}

In our Twig Form of the Games Entity, we could easily render the field using form_row or rendering the entire form once with Twig:

{{ form_start(games_form) }}
    {#
        Render all widgets of the Form
    #}
    {{ form_widget(games_form) }}

    <input type="submit" value="Create Game" />
{{ form_end(games_form) }}

But this would produce the following output in our project:

Twig Custom Render With Entity

According to your CSS or design rules, you don't want this because it's pretty ugly, for you and for the user. In our project, every category has an icon (image) and we want to be able to display some kind of panel with the same checkbox but that displays the name of the category and the icon as well and for that, we need to retrieve every entity of every checkbox.

Retrieving Entity Object with Twig

The first that you need to know is that when you work with an EntityType field that is expanded and allows multiple selections, is that the default widget renders a group of checkbox, so you can iterate over them with a for loop. As in our GamesForm the Category field is named as "Categories", we could render every single widget as:

{% for CategoryField in GamesForm.Categories %}
    <div>
        {{ form_row(CategoryField) }} <br>
    </div>
{% endfor %}

However it stills pretty ugly (although we know how to customize it now):

Twig Entity Field Custom Render

As previously mentioned, every Category Entity has a property namely icon that stores the name of the icon of every category, so we could generate a fancier widget to select the category in the form retrieving its entity to know which is the Icon of every Entity. This can be achieved as follows:

{% for CategoryField in GamesForm.Categories %}
    
    {# store index of the category in a variable #}
    {% set index = CategoryField.vars.value %}

    {# get entity object from its index in the Categories Field #}
    {% set entity = GamesForm.Categories.vars.choices[index].data %}
    
    {#
        The entity variable contains a CategoryEntity with all its properties.
        So we can now render    
    #}

    <div class="col-md-4">
        <div class="nk-feature-1">
            <div class="nk-feature-icon">
                <!-- Render the Icon of the Category -->
                <img src="{{ asset('uploads/icons/' ~ entity.icon ) }}" alt="">
            </div>
            <div class="nk-feature-cont">
                <h3 class="nk-feature-title">
                    {{ form_label(category_type) }}
                </h3>
                <h3 class="nk-feature-title text-main-1">
                    {{ form_widget(category_type) }}
                </h3>
            </div>
        </div>
    </div>
{% endfor %}

Which in our project would generate the following widgets:

Twig Retrieve Entity of EntityType field

Looks better right? As you can see, the entity of every checkbox of the EntityType field can be retrieved from the form.FieldName.vars.choices object that contains the choices of the field. To obtain the correct entity you just need to specify the index of the choices array and retrieve the entity from the data property.

Happy coding !


Senior Software Engineer at Software Medico. Interested in programming since he was 14 years old, Carlos is a self-taught programmer and founder and author of most of the articles at Our Code World.

Sponsors