【问题标题】:Using JOIN in Symfony2/Doctrine SQL在 Symfony2/Doctrine SQL 中使用 JOIN
【发布时间】:2012-11-13 01:33:23
【问题描述】:

我在尝试使用 QueryBuilder 或 DQL 时遇到问题。

我有以下关系:

用户 配置文件 RouteGroup Route

我想制作一个 DQL,列出特定用户可以访问的所有路由。 我可以使用以下代码获取此信息:

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

出于显而易见的原因,我不能使用此代码,否则我的服务器会超载,哈哈。

我尝试了以下方法:

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

有人可以帮忙吗???

更新:我尝试了 Zeljko 的解决方案并制作了这个脚本:

    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')”更改为“->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.

【问题讨论】:

  • 要回答您的更新,您不能只选择 u 和 r.. 到 r 的所有内容也必须选择。所以你需要 select('u, p, rg, r')

标签: php symfony doctrine dql query-builder


【解决方案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();

【讨论】:

  • 现在您应该尝试了解左连接和内连接之间的区别,它们非常不同,内连接可以为您省去很多麻烦。最简单的方法;创建类别有许多产品关系。获取类别时,做产品的innerJoin;您只会获得其中实际包含产品的类别。真的很酷,特别是当你将它与“WITH”子句结合使用时。
  • 没问题。我已经知道内连接和左连接之间的区别了。
【解决方案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();

我不知道具体原因,但如果您不包含实体,那么 hydrator 将不知道您用于实体的别名。

我希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-20
    • 1970-01-01
    相关资源
    最近更新 更多