yokai/many-to-many-matrix-bundle

Render a Doctrine ManyToMany relation has matrix form type

v1.1 2016-05-31 10:13 UTC

This package is auto-updated.

Last update: 2024-03-25 10:51:24 UTC


README

This bundle aims to render Doctrine ManyToMany relations as a matrix in a Symfony form.

Installation

Add the bundle as dependency with Composer

composer require yokai/many-to-many-matrix-bundle

Enable the bundle

<?php
// config/bundles.php

return [
    // ...
    Yokai\ManyToManyMatrixBundle\YokaiManyToManyMatrixBundle::class => ['all' => true],
];

Usage

Let's take an example : our application is handling Symfony's security with 2 Doctrine entity : User and Role. There is a ManyToMany between Role and User.

<?php

namespace App\Entity;

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

#[ORM\Entity]
#[ORM\Table(name: 'user')]
class User
{
    #[ORM\Column(type: 'integer')]
    #[ORM\Id]
    #[ORM\GeneratedValue]
    private ?int $id = null;

    #[ORM\Column(type: 'string', unique: true)]
    private string $email;

    /**
     * @var Collection<Role>
     */
    #[ORM\ManyToMany(targetEntity: Role::class, inversedBy: 'users')]
    private Collection $roles;

    public function __toString(): string
    {
        return $this->email;
    }

    //...
}
<?php

namespace App\Entity;

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

#[ORM\Entity]
#[ORM\Table(name: 'role')]
class Role
{
    #[ORM\Column(type: 'integer')]
    #[ORM\Id]
    #[ORM\GeneratedValue]
    private ?int $id = null;

    #[ORM\Column(type: 'string', unique: true)]
    private string $role;

    /**
     * @var Collection<User>
     */
    #[ORM\ManyToMany(targetEntity: User::class, inversedBy: 'roles')]
    private Collection $users;

    public function __toString(): string
    {
        return $this->role;
    }

    //...
}

I want to create a form matrix that will display the relation of these entities.

<?php

namespace App\Controller;

use App\Entity\Role;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Yokai\ManyToManyMatrixBundle\Form\Type\ManyToManyMatrixType;

class MatrixController extends AbstractController
{
    #[Route(path: '/role-matrix', name: 'role-matrix')]
    public function roleMatrixAction(Request $request, EntityManagerInterface $manager): Response
    {
        $roles = $manager->getRepository(Role::class)->findAll();

        $form = $this->createForm(
            ManyToManyMatrixType::class,
            $roles,
            [
                'class' => Role::class,
                'association' => 'users',
            ]
        );

        $form->handleRequest($request);
        if (!$form->isSubmitted() || !$form->isValid()) {
            return $this->render('role-matrix.html.twig', [
                'form' => $form->createView(),
            ]);
        }

        foreach ($roles as $role) {
            $manager->persist($role);
        }

        $manager->flush();

        return $this->redirectToRoute('role-matrix');
    }
}
{% extends 'base.html.twig' %}

{% block body %}
    {{ form_start(form) }}
        {{ form_widget(form) }}
        <button type="submit" class="btn btn-primary">update matrix</button>
    {{ form_end(form) }}
{% endblock %}

Screenshot

Important Notes

In the example above, we must note several IMPORTANT things.

Owning side

You MUST work with the owning side of your association (i.e. the entity that has the ìnversedBy attribute on its ManyToMany property)

__toString

The two entities MUST have a __toString method to render the label

MIT License

License can be found here.

Authors

The bundle was originally created by Yann Eugoné. See the list of contributors.