Doctrine多对多自关联Article实体如何用DQL查询关联子文章
问题解答
报错原因说明
你之前执行的查询报错是因为children是多值关联集合字段,DQL不支持直接对多值集合使用等于运算符做比对,仅支持对单值字段、单值关联字段做直接等于判断。
目标SQL转DQL实现
你不需要直接操作中间表,基于你已经定义的自关联属性,用QueryBuilder实现的代码如下:
// 在ArticleRepository类中添加该方法 public function findRelatedArticlesBySlug(string $slug): array { return $this->createQueryBuilder('a') ->select('a.slug') // 关联当前文章的父文章(也就是查询条件里的源文章) ->innerJoin('a.parents', 'source_article') ->where('source_article.slug = :target_slug') ->setParameter('target_slug', $slug) ->getQuery() ->getSingleColumnResult(); }
如果你希望和你给出的原生SQL逻辑完全对齐,使用子查询实现的写法如下:
// 在ArticleRepository类中添加该方法 public function findRelatedArticlesBySlug(string $slug): array { // 子查询:获取指定slug文章关联的所有子文章ID $subQueryBuilder = $this->createQueryBuilder('source_article') ->select('child_article.id') ->innerJoin('source_article.children', 'child_article') ->where('source_article.slug = :target_slug'); return $this->createQueryBuilder('a') ->select('a.slug') ->where($this->expr()->in('a.id', $subQueryBuilder->getDQL())) ->setParameter('target_slug', $slug) ->getQuery() ->getSingleColumnResult(); }
DQL访问中间表的说明
- 无额外字段的多对多中间表:你当前定义的中间表仅包含两个外键关联字段,这种情况不需要在DQL里直接访问中间表,Doctrine会在你对
children/parents属性做join操作时自动拼接中间表的关联逻辑。 - 需直接操作的中间表:如果你有特殊需求要直接操作中间表(比如中间表存了关联时间、关联类型等额外字段),需要将中间表定义为独立的实体类,将原有的双向多对多关联拆分为两个一对多关联:
Article一对多ArticleArticle多对一Article,之后就可以在DQL中直接查询ArticleArticle实体来操作中间表数据。
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

