Я создаю большой фильтр if и where условий с помощью Doctrine.
Грубая идея выглядит примерно так:
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select(...)->from(...)->joins(...)
if ($params['param1']) {
$qb->where(...)
}
if ($params['param2']) {
$qb->andWhere(...)
}
if ($params['param3']) {
$qb->andWhere(...)
}
Проблема, которую я ударил, заключается в том, что мне нужно использовать "andWhere" с "orWhere", но я хочу, чтобы "orWhere" сравнивался с этим одиночным "andWhere", а не со всем запросом, который я создал.
Так будет выглядеть примерно так:
if ($params['param4']) {
$qb->andWhere(...)
->orWhere(...)
}
Если я сделаю так, как только я использую orWhere, он будет игнорировать все для param1, param2, param3, когда все, что я хочу, это сравнить его с param4s, где условие.
Я решил, что мне нужно использовать подзапрос, но я действительно потерял, как это сделать в Доктрине. Может ли кто-нибудь указать мне в правильном направлении, как это сделать?
В таких случаях вы можете полагаться на класс Expr
который содержит методы, необходимые для создания более сложных запросов. Все, что вам нужно знать, описано в документации Doctrine в разделе Query Builder.
Текущая документация фактически дает пример, который почти соответствует указанному вами случаю использования. Вы могли бы написать что-то вроде этого, например:
$qb->andWhere($qb->expr()->orX(
$qb->expr()->eq('u.id', '?1'),
$qb->expr()->like('u.nickname', '?2')
));
Главное преимущество использования класса Expr
заключается в том, что вы можете в значительной степени написать какую-либо комбинацию с ним, и для этого вы получите правильный DQL. Однако он может быть довольно подробным.
При этом вы также можете напрямую написать свое условие OR в andWhere
:
$qb->andWhere('u.id = ?1 OR u.nickname = ?2');
andWhere
вместо того,where
при первом звонке. Это ничего не меняет для доктрины и позволяет избежать сброса ваших условий