我将把我的答案分成简短的解释(和替代答案)。
简短说明:
SELECT a.field1
, ...
, a.fieldN
, (SELECT COUNT(c.id) FROM Comment c WHERE c.article_id = a.id) num_comments
FROM Article a
然后作为 ARRAY 水合物,它会返回您所期望的。
长解释:
每当您引用实体本身时(在您的情况下为“SELECT a”),这意味着您正在请求返回与任何其他元素隔离的整个实体。默认情况下,Doctrine 始终将此实体分配给索引 0,并根据您选择的 FROM 实体的数量继续。要更改此行为,您所要做的就是为实体设置别名,就像您对子查询所做的那样:
SELECT a AS article
, (SELECT COUNT(c.id) FROM Comment c WHERE c.article_id = a.id) AS num_comments
FROM Article a
这将返回到类似的内容:
array(
0 => array(
"article" => array(
"id" => 1,
"title" => "Title",
),
"num_comments" => 15
),
1 => array(
"article" => array(
"id" => 2,
"title" => "Title",
),
"num_comments" => 20
)
);
如果您不希望返回整个实体,则可以使用 PARTIAL 支持并仅返回您感兴趣的字段。让我们支持您只需要 id(强制性,因为它是实体标识符)和标题:
SELECT PARTIAL a.{id, title} AS article
, (SELECT COUNT(c.id) FROM Comment c WHERE c.article_id = a.id) AS num_comments
FROM Article a
另一种方法是将结果封装到 DTO 中。当您决定将值水合为对象时,这将提供更多的 OO 控制。DQL 看起来像这样:
SELECT NEW ArticleDTO(a, COUNT(c.id))
FROM Article a
LEFT JOIN a.comments c
GROUP BY a.id
您不能将整个子查询作为参数放置的原因是由于 DQL 的限制。从来没有人请求过完整的子查询,所以现在我们遵循 JPA 建议的 ScalarExpression。
干杯,
吉尔赫姆·布兰科