Использование 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();

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

ОБНОВЛЕНИЕ: я попробовал решение Желько и сделал это 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();

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

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

Если я меняю "- > выберите ('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.

Ответ 1

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

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

Ответ 2

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

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

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

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

Ответ 3

Я не эксперт в Doctrine, но просто решил очень похожую проблему. Я исправил свою проблему, включив все сущности, которые вы использовали в соединениях в 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();

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

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