🎻
[Doctrine] 「子エンティティを一定以上所有しているかどうか」で絞り込むQueryBuilderの書き方
だいぶニッチだと思いますが備忘録です😅
要件
-
ParentエンティティとChildエンティティがある -
ParentエンティティはOneToManyでChildエンティティを所有している -
ParentエンティティにはwantsToHaveChildrenMoreThanという整数型のプロパティがあり、「Childエンティティを何個以上所有したいか」という情報を持っている - 実際に所有している
Childエンティティの個数がwantsToHaveChildrenMoreThanの数以上であるようなParentエンティティのみを絞り込んで取得したい
やり方
class ParentRepository extends ServiceEntityRepository
{
// ...
public function findEnoughChildren()
{
return $this->createQueryBuilder('p')
->leftJoin('p.children', 'c')
->groupBy('p.id, p.wantsToHaveChildrenMoreThan')
->having('count(c) >= p.wantsToHaveChildrenMoreThan')
->getQuery()
->getResult()
;
}
}
出来上がってみればとてもシンプルなのですが、SQL力が低くて結構苦労しました😅
-
WHERE句ではなくHAVING句を使う - そのために
p.idp.wantsToHaveChildrenMoreThanの両方でGROUP BYしておく
というのがポイントですね。
まとめ
- DoctrineのQueryBuilderは便利なんですが、複雑なクエリを書くときは、「先にSQLを書いてみて、それをDQLでどう実現するか考える」という順序で取り組むほうが効率的な気がします😇
Discussion