web-dev-qa-db-fra.com

Utiliser JOIN dans Symfony2 / Doctrine SQL

J'ai un problème lors de l'utilisation de QueryBuilder OR DQL.

J'ai la relation suivante:

Utilisateur <-1: n-> Profil <-n: m-> RouteGroup <-1: n-> Route

Je voudrais faire un DQL qui répertorie toutes les routes auxquelles un utilisateur spécifique a accès. Je peux obtenir ces informations avec le code suivant:

$usr = $this->container->get('security.context')->getToken()->getUser();
foreach ($usr->getProfiles() as $profile){
    foreach ($profile->getRoutegroups() as $routegroup){
        var_dump($routegroup->getRoutes()->toArray());
     }
}

Pour une raison évidente, je ne peux pas utiliser ce code, sinon je surchargerai mon serveur, LOL.

J'ai essayé les approches suivantes:

DQL:

$em->createQuery('SELECT p FROM CRMCoreBundle:User u
                  JOIN CRMCoreBundle:Profile p
                  JOIN CRMCoreBundle:RoleGroup rg
                  JOIN CRMCoreBundle:Role r
                  WHERE
                    u.id=:user')
        ->setParameter('user', $user->getId())
        ->getResult();

QueryBuilder (j'ai essayé d'utiliser u.profiles - le nom de la relation au lieu de l'entité - mais cela n'a pas fonctionné également):

$em->createQueryBuilder()
        ->select('r')
        ->from('CRMCoreBundle:User', 'u')
        ->innerJoin('u.profiles','p')
        ->where('u.id = :user_id')
        ->setParameter('user_id', $user->getId())
        ->getQuery()
        ->getResult();

Quelqu'un peut-il aider s'il vous plaît ???

MISE À JOUR: J'ai essayé la solution de Zeljko et fait ce script:

    return $this->getEntityManager()
        ->createQueryBuilder()
        ->select('u, r')
        ->from('CRMCoreBundle:User', 'u')
        ->innerJoin('u.profiles','p')
        ->innerJoin('p.routegroups','rg')
        ->innerJoin('rg.routes','r')
        ->where('u.id = :user_id')->setParameter('user_id', $user->getId())
        ->getQuery()
        ->getResult();

Mais j'ai eu cette erreur:

The parent object of entity result with alias 'r' was not found. The parent alias is 'rg'.

Si je change "-> sélectionnez ('u, r')" en "-> sélectionnez ('r')" j'obtiens ceci:

[Semantical Error] line 0, col -1 near 'SELECT r FROM': Error: Cannot select entity through identification variables without choosing at least one root entity alias.
14
Marcelo Diotto

Après avoir essayé quelques alternatives, j'ai découvert que je pouvais faire une recherche inverse, en commençant par les itinéraires vers les utilisateurs. La solution était la suivante:

return $this->getEntityManager()
        ->createQueryBuilder()
        ->select('r')
        ->from('CRMCoreBundle:Route', 'r')
        ->innerJoin('r.routegroup','rg')
        ->innerJoin('rg.profiles','p')
        ->innerJoin('p.users','u')
        ->where('u.id = :user_id')
        ->setParameter('user_id', $user->getId())
        ->getQuery()
        ->getResult();
22
Marcelo Diotto

Dans votre DQL, vous récupérez des utilisateurs mais vous avez demandé comment récupérer des itinéraires. De quoi avez-vous réellement besoin?

Quoi qu'il en soit, dans RoutesRepository:

$this->createQueryBuilder("r")
  ->innerJoin("r.Profiles", "p")
  ->innerJoin("p.User", "u")
  ->where("u=:user")->setParameter("user", $user)

Je ne comprends peut-être pas la relation, mais je pense que vous pouvez changer cela pour refléter votre code. Vous devez utiliser innerJoin, pas leftJoin.

3
Zeljko

Je ne suis pas un expert de Doctrine, mais je viens de résoudre un problème très similaire. J'ai résolu mon problème en incluant toutes les entités que vous utilisiez dans les jointures dans la partie SELECT de l'instruction.

Je n'ai pas testé cela, mais cela devrait fonctionner.

$em->createQuery('SELECT u, p, rg, r FROM CRMCoreBundle:User u
              JOIN CRMCoreBundle:Profile p
              JOIN CRMCoreBundle:RoleGroup rg
              JOIN CRMCoreBundle:Role r
              WHERE
                u.id=:user')
    ->setParameter('user', $user->getId())
    ->getResult();

Je ne sais pas exactement pourquoi, mais si vous n'incluez pas les entités, l'hydrateur ne connaît pas les alias que vous utilisez pour les entités.

J'espère que cela aide.

3
Damien Whaley