Doctrine QueryBuilder groupBy关系不起作用

时间:2017-01-20 14:06:08

标签: php doctrine-orm

我有以下查询:

$query = $qb->select('p')
   ->from(get_class($page), 'p')
        ->innerJoin('p1.translations', 't')
        ->groupBy('p.id')
        ->addGroupBy('t.id')
        ->getQuery();

Doctrine返回上面的内容,如:

Page entity -> [translation 1, translation 2, translation 3]

但我希望结果如下:

Page entity 1 -> translation 1
Page entity 1 -> translation 2
Page entity 1 -> translation 3

有谁知道我怎么做到这一点?我想返回一个实体列表。

1 个答案:

答案 0 :(得分:0)

首先,两个groupBy都是完全多余的,假设您分组的两个id字段是其各自表的主键。对于任何给定的(p.id, t.id)组合,无论您是否进行分组,最多只能有一个结果。

其次,即使您加入了翻译表,也没有从中获取任何数据(t中没有->select())。它只是出现这种方式,因为当你调用$page->getTranslations()时,学说“神奇地”在背景中加载数据(假设你的getter被这样调用)。

第三,您的问题不在于groupBy。在对查询结果进行保湿时,您完全误解了ORM实际上做了什么。从您的代码生成的SQL查询实际上以您期望的方式返回结果,并且“Page entity 1”重复多次。

然而,现在是水合步骤。 Doctrine读取第一个结果行,构建“页面实体1”和“翻译1”实体,链接它们并将它们添加到它的内部实体注册表中。然后,对于第二个结果,Doctrine注意到它已经水化了“Page entity 1”对象并且(这是关键部分!)重用第一行中的相同对象,添加第二个翻译到现有对象的->translation集合。即使您稍后在代码中以完全不同的查询再次阅读“页面实体1”,您仍然会再次获得相同的PHP对象。

这种行为是Doctrine所做的核心。基本上,数据库中的任何表行都将始终由PHP端的单个对象进行镜像,无论您多久或以何种方式从数据库中实际读取它。

总而言之,您的查询应如下所示:

$query = $qb->select('p, t')
    ->from(get_class($page), 'p')
    ->innerJoin('p.translations', 't')
    ->getQuery();

如果你真的需要遍历所有(p,t)组合,请使用嵌套循环:

foreach ($query->getResult() as $p) {
    foreach ($p->getTranslations() as $t) {
        // do something
    }
}

编辑:如果您的关系是双向的,您也可以转过身来查询:

$query = $qb->select('t, p')
    ->from('My\Bundle\Entity\Translation', 't')
    ->innerJoin('t.page', 'p')
    ->getQuery();

现在在您的示例中,您实际上获得了3个结果,您可以在单个foreach()中迭代。您仍然只能获得一个“页面实体1”对象,查询结果中的所有翻译都指向它。