🎻

[Doctrine] 「子エンティティを一定以上所有しているかどうか」で絞り込むQueryBuilderの書き方

2020/06/25に公開

だいぶニッチだと思いますが備忘録です😅

要件

  • Parent エンティティと Child エンティティがある
  • Parent エンティティは OneToManyChild エンティティを所有している
  • 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でどう実現するか考える」という順序で取り組むほうが効率的な気がします😇
GitHubで編集を提案

Discussion