Doctrine: несколько запросов json_contains в одном предложении where - PullRequest
0 голосов
/ 05 мая 2020

Я пытаюсь решить следующую проблему:

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

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

У меня есть массив с ролями фактического пользователя:

$roles= array('role1','role2','role3')

Теперь мне нужно сделать что-то вроде этого:

select *
from notification
where (mandant_id = 'xxxxx' or mandant_id is null)
AND (JSON_CONTAINS(roles, '\"role1\"', '$') = 1 OR JSON_CONTAINS(roles, '\"role3\"', '$') = 1)
ORDER BY created_at DESC LIMIT 10

обязательная часть проста:

$queryBuilder->where('notification.mandantId = :mandantId OR notification.mandantId is null');
$queryBuilder->setParameter('mandantId', $userMandantId, MandantIdDoctrineType::NAME); 

теперь мне нужно l oop над массивом $ role и поместить запросы в одно предложение where в сочетании с OR.

Мне нужно al oop как:

foreach($roles AS $role){
  ....build up the query sting....
}

с результатом вроде:

$qb->andWhere(JSON_CONTAINS(roles, '\"role1\"', '$') = 1 OR JSON_CONTAINS(roles, '\"role3\"', '$') = 1)

не удалось найти правильный путь. пожалуйста, помогите мне! :)

Ответы [ 2 ]

0 голосов
/ 06 мая 2020

спасибо @bananaapple, ты сделал мой день.

Он отлично работал, за исключением второй oop, которую мне пришлось вставить и переделать -> и где запрос.

$roles            = ['role1', 'role2', 'role3'];
$roleQueryParts = [];

$i = 0;
foreach ($roles as $role) {
    ++$i;

    // build the individual conditionals of your OR chain
    $roleQueryParts[] = "JSON_CONTAINS(roles, :role$i, '$') = 1";

}

// fuse the conditionals into one string of condition 1 OR condition 2 OR...
$roleQuery = implode(' OR ', $roleQueryParts);

// fire the query
$queryBuilder->andWhere($roleQuery);

$i = 0;
foreach ($roles as $role) {
    ++$i;

    // set the role parameters - note we're passing them as strings wrapped in "
    $queryBuilder->setParameter('role' . $i, '"' . $role . '"');

}

Это отлично сработало для меня. Спасибо!

0 голосов
/ 05 мая 2020

Что-то в этом роде должно помочь:

$roles            = ['role1', 'role2', 'role3'];
$roleQueryParts = [];

$i = 0;
foreach ($roles as $role) {
    ++$i;

    // build the individual conditionals of your OR chain
    $roleQueryParts[] = "JSON_CONTAINS(roles, :role$i, '$') = 1";

    // set the role parameters - note we're passing them as strings wrapped in "
    $queryBuilder->setParameter('role' . $i, '"' . $role . '"');
}

// fuse the conditionals into one string of condition 1 OR condition 2 OR...
$roleQuery = implode(' OR ', $roleQueryParts);

$queryBuilder->andWhere($roleQuery);

Возможно, вам придется поместить бит setParameter() в отдельный foreach после andWhere() - я не могу вспомнить, было ли Doctrine позволит вам установить параметры перед добавлением их в SQL.

...