Использование JOIN в Symfony2 / Doctrine SQL

У меня проблема при попытке использовать QueryBuilder OR DQL.

У меня есть следующее соотношение:

Пользователь <-1: n-> Профиль <-n: m-> RouteGroup <-1: n-> Маршрут

Я хотел бы создать DQL, в котором перечислены все маршруты, к которым имеет доступ определенный пользователь. Я могу получить эту информацию со следующим кодом:

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

По понятной причине я не могу использовать этот код, иначе я перегружу свой сервер, LOL.

Я пробовал следующие подходы:

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 (я попытался использовать u.profiles – имя отношения вместо объекта – но это тоже не сработало):

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

Может кто-нибудь помочь пожалуйста ???

ОБНОВЛЕНИЕ: я попробовал решение Желько и сделал этот скрипт:

  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(); 

Но я получил эту ошибку:

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

Если я меняю "-> select ('u, r')" to "-> select ('r')", я получаю следующее:

 [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. 

Попробовав несколько альтернатив, я обнаружил, что могу сделать обратный поиск, начиная с маршрутов до пользователей. Решение было следующим:

 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(); 

В вашем DQL вы выбираете пользователей, но вы спрашиваете, как выбирать маршруты. Что на самом деле вам нужно?

В любом случае, в RoutesRepository:

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

Я мог бы не понимать отношения, но я думаю, вы можете изменить это, чтобы отразить ваш код. Вы должны использовать innerJoin, а не leftJoin.

Я не специалист по Доктрине, но просто решил очень похожую проблему. Я исправил свою проблему, включив все сущности, которые вы использовали в соединениях в SELECT-части инструкции.

Я не тестировал это, но это должно сработать.

 $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(); 

Я не знаю точно, почему, но если вы не включаете сущности, то гидрант не знает о псевдонимах, которые вы используете для сущностей.

Надеюсь, это поможет.