Как правильно в доктрине построить запрос для фильтра со сложными условиями?

Делаю фильтрацию каталога. В нем много параметров для фильтрации, упрощенно строка выглядит примерно так
/?isStock@bool=1&year@range=2015|2019&year@sort=>&color@array=красный|синий&brand@array=bmw|honda


я придумал себе алгоритм для это строки, может это конечно не очень - до чего додумался, пытался искать другие варианты, только эластиксерч подошел по параметрам, но это избыточно для моего проекта

я сделал базовый класс Параметра и расширил базовый класс специфическими типами в которых строится запрос
типа Simple, Bool, Range (плюс еще сортировка и значение для пейджинга)

каждый тип сам строит запрос, например это метод Range типа
public function buildQuery(QueryBuilder $qb): QueryBuilder
    {
        [$normalizedKey] = $this->getKeys($qb); //значение вместе с алиасом

        if ($this->getFrom()) {
            $qb->andWhere($qb->expr()->andX(
                $qb->expr()->gte($normalizedKey, $this->getFrom())
            ));
        }

        if ($this->getTo()) {
            $qb->andWhere($qb->expr()->andX(
                $qb->expr()->lte($normalizedKey, $this->getTo())
            ));
        }

        return $qb;
    }


все прекрасно работает, но проблема в том что есть ОБЯЗАТЕЛЬНЫЕ параметры(тот же Range) -
то есть должно соблюдаться условие AND
Но у типа Array другое условие например color@array=красный|синий, то есть в результатх с обязательными параметрами нужно найти какой то из множества, или красный или синий
Я построил такой запрос и он работает
public function buildQuery(QueryBuilder $qb): QueryBuilder
    {
        [$normalizedKey, $key] = $this->getKeys($qb);
        $values = $this->getValue();

        $qb->andWhere($normalizedKey . ' IN (:values)')->setParameter('values', $values, Connection::PARAM_STR_ARRAY);

        return $qb;
    }

НО, если таких фильтров несколько - все рушится, условие не подходит, не пойму почему, глову уже сломал
есть вариант фильтровать уже на фронте с помощью js

Подскажите пожалуйста есть ли какие то варианты
на всякий случай приложу дамп DQL
"SELECT c FROM App\Entity\Car c WHERE c.isStock = :isStock AND c.year >= 2015 AND c.year <= 2019 AND c.color IN (:values) AND c.brand IN (:values)"
  • Вопрос задан
  • 132 просмотра
Решения вопроса 1
Maksclub
@Maksclub
maksfedorov.ru
Вы в цикле для разных фильтров добавляет в один объект QueryBuilder параметры с одним ключом values, потом при сборке запроса Doctrine достает первый найденный Parameter с ключом values (а их таких несколько, но ей достаточно первого).

Код Доктрины:
5f21da43a9cea902909869.png

То есть для цвета, года, уровня — всегда достается первый параметр с ключом values

Предлагаю подставлять вместо этого слова разный алиас, например key:
[$normalizedKey, $key] = $this->getKeys($qb);

$qb
	->andWhere(sprintf('%s IN (:%s)', $normalizedKey, $key))
	->setParameter($key, $this->getValue());
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы