Symfony中如何使用DQL查询多对多关联中间表数据
解答
你完全不需要使用原生SQL,DQL原生支持这类多对多关联查询,哪怕框架自动生成的中间表product_category没有对应实体类也可以正常实现。
Doctrine ORM对ManyToMany关联做了底层封装,只要你在实体类中正确配置了多对多关联映射,框架会自动处理中间表的拼接逻辑,不需要你手动把无实体的中间表作为独立查询对象关联。
具体实现方式
- 首先确认
Category实体中已经配置了和Product的双向多对多关联,参考配置(以PHP 8 Attributes写法为例):
// Category实体类内的关联配置 #[ORM\ManyToMany(targetEntity: Product::class, inversedBy: 'categories')] #[ORM\JoinTable(name: 'product_category')] #[ORM\JoinColumn(name: 'category_id', referencedColumnName: 'id')] #[ORM\InverseJoinColumn(name: 'product_id', referencedColumnName: 'id')] private Collection $products; public function __construct() { $this->products = new ArrayCollection(); }
- 关联配置完成后,直接在QueryBuilder中通过实体的关联属性做关联即可,不需要手动指定中间表:
$qb = $entityManager->createQueryBuilder(); $result = $qb->select('c', 'p') ->from(Category::class, 'c') ->leftJoin('c.products', 'p') // 直接关联Category上定义的products属性,Doctrine自动拼接中间表关联逻辑 ->getQuery() ->getResult();
逻辑说明
上述代码生成的底层SQL和你给出的原生SQL逻辑完全匹配,Doctrine会自动补充中间表product_category的关联条件:
SELECT * FROM category c LEFT JOIN product_category ON c.id = product_category.category_id LEFT JOIN product p ON p.id = product_category.product_id
你之前参考的join写法是用来关联存在对应实体类的独立表的,不适用于ManyToMany自动生成的无实体中间表场景——这类中间表本来就不需要手动创建实体,通过实体上的关联属性直接关联是Doctrine推荐的标准写法。
如果你的需求里不需要查询关联的产品具体字段,只需要获取分类和产品的关联关系,甚至不需要写join,直接在Category实体中配置好关联后,调用$category->getProducts()就能直接拿到对应关联的产品数据,Doctrine会懒加载自动查询中间表数据。
内容的提问来源于stack exchange,提问作者Michaël Godinho Da Costa
相关产品推荐
相关产品推荐

