Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/228.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 条令QueryBuilder groupBy关系不起作用_Php_Doctrine Orm - Fatal编程技术网

Php 条令QueryBuilder groupBy关系不起作用

Php 条令QueryBuilder groupBy关系不起作用,php,doctrine-orm,Php,Doctrine Orm,我有以下疑问: $query = $qb->select('p') ->from(get_class($page), 'p') ->innerJoin('p1.translations', 't') ->groupBy('p.id') ->addGroupBy('t.id') ->getQuery(); 条令返回上述内容,如下所示: Page entity -> [translati

我有以下疑问:

$query = $qb->select('p')
   ->from(get_class($page), 'p')
        ->innerJoin('p1.translations', 't')
        ->groupBy('p.id')
        ->addGroupBy('t.id')
        ->getQuery();
条令返回上述内容,如下所示:

Page entity -> [translation 1, translation 2, translation 3]
但我想要的结果是:

Page entity 1 -> translation 1
Page entity 1 -> translation 2
Page entity 1 -> translation 3
有人知道我怎么做吗?我想返回一个实体列表

首先,假设分组依据的两个id字段都是各自表的主键,那么这两个groupBy是完全多余的。对于任何给定的p.id、t.id组合,无论是否分组,最多只能有一个结果

第二,即使您正在加入translations表,您也不会从中获取任何数据,因为您的->选择中不存在t。它就是这样出现的,因为当您调用$page->getTranslations时,如果您的getter是这样调用的,那么条令会神奇地在后台加载数据

第三,你的问题与groupBy无关。您完全误解了ORM在处理查询结果时的实际操作。doctrine从您的代码生成的SQL查询实际上将以您期望的方式返回结果,页面实体1将重复多次

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

这种行为是教义的核心。基本上,数据库中的任何表行都将始终由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中迭代。您仍然只能得到一个页面entity 1对象,查询结果中的所有翻译都指向它。

我看不出有什么理由不为此创建自定义对象。我知道条令并没有提供一个水合器,但可以。学说是抽象的,这意味着它可以通过开闭原理进行扩展。我认为你因为否认这个事实而误解了教义。是的,你可以,但你不应该。首先,编写一个定制的水合器不是一件容易的事情,仅仅为了节省一个foreach会是一个奇怪的权衡。其次,假设您这样做了,现在您有了页面实体1的三个独立实例。对这三个参数进行一些更改,然后调用$em->flush。实体管理器应该将哪些更改保存回数据库?我同意这将需要大量工作。当使用过滤器时,当过滤器值更改时,也会获得相同的结果。那么,是由ORM来保护我,还是由开发人员的专业知识来保护自己呢?我认为这取决于开发人员。如果你不想让框架帮助你,为什么你首先要使用框架?也许原始SQL更适合您。