14/12/2020

Inner join many to many avec symfony et doctrine

Récupération des managers

Vous avez par exemple deux entités User et Role. Ces deux entité sont liées par une relation de ManyToMany c’est à dire qu’un utilisateur a un ou plusieurs rôles et qu’un rôle a un ou plusieurs utilisateurs.

Niveau base de données, doctrine crée une table intermédiaire comportant les (user_id et role_id) qui permet de faire la relation.

Cependant, en Symfony nous ne parlons qu’en entité. Pour récupérer tout les utilisateurs du rôle ROLE_RESPONSABLE, il faut faire un code DQL de ce genre :

/**
 * @return Appel[] Returns an array of Appel objects
 */
 public function getManagers()
 {
 	return $this->createQueryBuilder('u')
    	->innerJoin('u.userRoles', 'r')
        ->andwhere('r.title LIKE :title')
        ->setParameter('title', 'ROLE_RESPONSABLE')
        ->getQuery()
        ->getResult();
 }
use App\Repository\UserRepository
...
/**
 * @Route("/blabla")
 */
class BlablaController extends AbstractController 
{
    public function new(UserRepository $userRepository)
    {
        $manager = $userRepository->getManagers(),
        ...
    }
}

Symfony, c’est vraiment se compliquer la vie pour rien. Pour rappel ce genre de chose se fait VRAIMENT TRÈS TRÈS SIMPLEMENT EN SQL classique. (C’est juste pour ceux qui on oublié ce qu’est le développement à la base.)

SELECT user.username, user.email
FROM user, user_role, role 
WHERE user_role.user_id = user.id
AND user_role.role_id = role.id
AND role.title = "ROLE_RESPONSABLE"
ORDER BY user.username

Ajout de la liste dans le formulaire

Si vous voulez par exemple afficher un <select> qui contient la liste des utilisateurs portant le rôle de responsable. Vous devez modifier votre formbuilder :

$form = $this->createForm(
    AppelType::class, 
    $appel, 
    [
        'managers' => $userRepository->getManagers(),
    ]
);
public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'managers' => [],
        ]);
    }
->add('responsable', EntityType::class, [
    'class' => User::class,
    'choice_label' => 'fullname',
    'label' => 'Nom du Responsable',
    'choices'  => $options['managers'],
])

Voilà…. C’est long et chiant. Sans ce genre de framework ça se fait en 3 sec.