Можно ли выполнить условие LIKE в запросе WHERE IN ARRAY в доктрине?

0

Я использую Doctrine QueryBuilder для создания запроса, чтобы выбрать группу пользователей по их окончаниям электронной почты. У меня есть массив окончаний электронной почты, например ['@someservice.com', '@anotherservice.com' ].

Я знаю, что я могу выбрать строку в массиве через WHERE IN:

$qb= $this
    ->createQueryBuilder('u')
    ->orderBy('u.id', 'asc')
    ->where('u.email IN (:emails)')
    ->setParameter('emails', [
        '@someservice.com',
        '@anotherservice.com'
    ]);

Тем не менее этот запрос для точных вхождений строки и, следовательно, запроса, конечно, вернет пустой набор результатов.

Вот почему я хочу сделать LIKE-поиск в массиве, но все же делаю что-то вроде:

$qb= $this
    ->createQueryBuilder('u')
    ->orderBy('u.id', 'asc')
    ->where('u.email LIKE IN (:emails)')
    ->setParameter('emails', [
        '%@someservice.com',
        '%@anotherservice.com'
    ]);

к сожалению, не удается. Есть ли какой-нибудь синтаксический сахар для выполнения такого запроса, или я должен сделать запрос с кучей вызовов orHaving?

  • 0
    LIKE IN не является признанным синтаксисом SQL AFAIK и, следовательно, вероятно, не поддерживается. Это не мешает вам расширить его с помощью вспомогательной функции, которая преобразует его в нечто подобное этому решению . HAVING , как всегда, последнее средство, это идеально вписывается в WHERE .
Теги:
arrays
doctrine2
sql-like

2 ответа

2
Лучший ответ

Я достиг чего-то подобного:

foreach($emailEndings as $index => $ending) {
    $qb->orWhere("u.email LIKE :email$index");
    $qb->setParameter("email$index", $ending);
}

Индекс имеет важное значение, поскольку в противном случае выбирается только последняя запись массива.

Имейте в orWhere что если у вас есть несколько статей, в которых вы попадете в проблему из-за предложения orWhere. Вы не можете изменить это в andWhere, так как это приведет к пусту набору результатов. В этом случае вам нужно будет сгруппировать условия в Orx для andWhere как это:

/**
 * @param QueryBuilder $qb
 */
protected function addInternalFilter(QueryBuilder $qb)
{
    $conditions = [];
    foreach ($this->emailEndings as $index => $ending) {
        $conditions[] = "u.email LIKE :string$index";
        $qb->setParameter("string$index", $ending);
    }

    if (empty($conditions)) {
        throw new \LogicException('Conditions are empty.');
    }

    $qb->andWhere(new Orx($conditions));
}
  • 0
    Грязное решение.
  • 0
    @ PawełKolanowski Не могли бы вы уточнить это? Что было бы лучше?
Показать ещё 1 комментарий
0

Вы не можете этого сделать. % для LIKE, LIKE не используется с IN.

Вы можете справиться с ним только с помощью OR:

->where("u.email LIKE '%@someservice.com' OR u.email LIKE '%@anotherservice.com'")
  • 0
    Я хочу избегать обслуживания запроса на выборку каждый раз, когда добавляется новое окончание электронной почты. Я хочу сохранить окончания электронной почты в массиве конфигурации. Отсюда важность итерации по массиву.
  • 0
    @ k0pernikus Я знаю, но вы не можете этого сделать, SQL не распознает синтаксис LIKE IN

Ещё вопросы

Сообщество Overcoder
Наверх
Меню