🎻
[Doctrine] QueryBuilderでIN句に配列を渡す/配列プロパティが目的の値を含んでいるかどうかで絞り込む
備忘録です。
QueryBuilderでIN句に配列を渡す
一見普通っぽいけどバギーなやり方(お勧めしない)
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Types\Types;
$ids = [1,2,3,4,5];
$qb = $fooRepository->createQueryBuilder('f');
$qb
->andWhere('f.id IN (:ids)')
->setParameter('ids', $ids, Types::ARRAY)
// または
->setParameter('ids', $ids, Connection::PARAM_INT_ARRAY)
->getQuery()
->getResult()
;
参考:
パラメータが配列じゃないときと同じ書き方なのでこれが標準的なやり方のような気もするのですが、Doctrineの公式ドキュメント で言及されておらず、標準のやり方が不明です😓
実際に使ってみるとなんか正常に動かない感じがしているので、個人的にはお勧めしません🙄
バギーじゃないやり方(お勧め)
$ids = [1,2,3,4,5];
$qb = $fooRepository->createQueryBuilder('f');
$qb
->andWhere($qb->expr()->in('f.id', $ids))
->getQuery()
->getResult()
;
または
$ids = [1,2,3,4,5];
$expr = $this->getEntityManager()->getExpressionBuilder();
$fooRepository->createQueryBuilder('f')
->andWhere($expr->in('f.id', $ids))
->getQuery()
->getResult()
;
この方法は、個人的な感覚として特に何も心配しなくても常に正常に動いてくれています。
なお、1つ注意点があって、 $ids
が空の配列だとSQLレベルのエラーになります。
参考:$query->expr()->in and notIn function does not support empty array · Issue #8033 · doctrine/orm
なので、渡す配列が空になり得る場合は、ちょっと強引ですが以下のように対処しておくとよいです。
->andWhere($ids ? $expr->in('f.id', $ids) : '1=0')
配列が空の場合には '1=0' という必ず false
になる式を andWhere()
に渡している、というものです。(もっといい方法ご存知の方は DM ください🙏)
プロパティの中身が配列のときに、その配列が目的の値を含んでいるかどうかで絞り込む
一瞬、IN句を使って右左辺を入れ替えればいいのかな?とか思ってしまいそうですが、この場合は普通に like
を使えばいいだけです✋
$postRepository->createQueryBuilder('p')
->andWhere('p.tags like :targetTag')
->setParameter('targetTag', sprintf('%%%s%%', $targetTag))
->getQuery()
->getResult()
;
参考:php - Is there a way to query if array field contains a certain value in Doctrine2? - Stack Overflow
Discussion