🎻
[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.id
p.wantsToHaveChildrenMoreThan
の両方でGROUP BY
しておく
というのがポイントですね。
まとめ
- DoctrineのQueryBuilderは便利なんですが、複雑なクエリを書くときは、「先にSQLを書いてみて、それをDQLでどう実現するか考える」という順序で取り組むほうが効率的な気がします😇
Discussion