Implementing a many-to-many relationship with Symfony forms involves using the EntityType field type with multiple selections enabled. In this example, we'll create a simple application with User and Role entities in a many-to-many relationship. We'll use checkboxes to allow multiple role selections when creating or editing a user.

 

Create the Entity Classes:

Create the User and Role entity classes and set up the many-to-many relationship between them.

// src/Entity/User.php
namespace App\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 */
class User
{
    // ... other properties and annotations ...

    /**
     * @ORM\ManyToMany(targetEntity="Role", inversedBy="users")
     * @ORM\JoinTable(name="user_roles")
     */
    private $roles;

    public function __construct()
    {
        $this->roles = new ArrayCollection();
    }

    // ... getters and setters ...
}

// src/Entity/Role.php
namespace App\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 */
class Role
{
    // ... other properties and annotations ...

    /**
     * @ORM\ManyToMany(targetEntity="User", mappedBy="roles")
     */
    private $users;

    public function __construct()
    {
        $this->users = new ArrayCollection();
    }

    // ... getters and setters ...
}

 

Create the Form Type Class:
Now, create the form type class for the User entity, including the EntityType field for the Role relationship with multiple selections enabled.

// src/Form/UserType.php
namespace App\Form;

use App\Entity\User;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class UserType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('username', TextType::class)
            // Add the EntityType field for the "roles" property with multiple selections enabled
            ->add('roles', EntityType::class, [
                'class' => 'App\Entity\Role', // Replace with your Role entity class
                'choice_label' => 'name', // Replace with the property to display in the checkboxes
                'multiple' => true, // Enable multiple selections
                'expanded' => true, // Display checkboxes instead of a dropdown
            ]);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => User::class,
        ]);
    }
}

 

Use the Form in a Controller:
Now, use the form in a controller to handle user creation and editing.

// src/Controller/UserController.php
namespace App\Controller;

use App\Entity\User;
use App\Form\UserType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class UserController extends AbstractController
{
    /**
     * @Route("/user/create", name="user_create")
     */
    public function createUser(Request $request): Response
    {
        $user = new User();
        $form = $this->createForm(UserType::class, $user);

        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {
            // Save the user to the database
            $entityManager = $this->getDoctrine()->getManager();
            $entityManager->persist($user);
            $entityManager->flush();

            // Redirect to the user list page or show a success message
            return $this->redirectToRoute('user_list');
        }

        return $this->render('user/create_user.html.twig', [
            'form' => $form->createView(),
        ]);
    }

    // ... other actions ...
}

 

Render the Form in a Twig Template:
Finally, render the form in a Twig template.

{# templates/user/create_user.html.twig #}
{% extends 'base.html.twig' %}

{% block content %}
    <h1>Create User</h1>
    {{ form_start(form) }}
    {{ form_row(form.username) }}
    {{ form_row(form.roles) }}
    <button type="submit">Create User</button>
    {{ form_end(form) }}
{% endblock %}

When you access the /user/create route, you'll see the "Create User" form with checkboxes to select multiple roles.

The roles will be loaded from the database and displayed with their names as options. When you submit the form, the selected roles will be associated with the created user in the many-to-many relationship.