Как использовать WHERE IN с Doctrine 2 - программирование
Подтвердить что ты не робот

Как использовать WHERE IN с Doctrine 2

У меня есть следующий код, который дает мне ошибку:

Message: Invalid parameter number: number of bound variables does not match number of tokens 

код:

public function getCount($ids, $outcome)
{
    if (!is_array($ids)) {
        $ids = array($ids);
    }
    $qb = $this->getEntityManager()->createQueryBuilder();
    $qb->add('select', $qb->expr()->count('r.id'))
       ->add('from', '\My\Entity\Rating r');
    if ($outcome === 'wins') { 
        $qb->add('where', $qb->expr()->in('r.winner', array('?1')));
    }
    if ($outcome === 'fails') {
        $qb->add('where', $qb->expr()->in('r.loser', array('?1')));
    }
    $qb->setParameter(1, $ids);
    $query = $qb->getQuery();
    //die('q = ' . $qb);
    return $query->getSingleScalarResult();
}

Данные (или $ids):

Array
(
    [0] => 566
    [1] => 569
    [2] => 571
)

Результат DQL:

q = SELECT COUNT(r.id) FROM \My\Entity\Rating r WHERE r.winner IN('?1')
4b9b3361

Ответ 1

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

Из исходного сообщения следующая строка кода:

$qb->add('where', $qb->expr()->in('r.winner', array('?1')));

Привязка именованного параметра как массива вызывает проблему с номером связанного параметра. Удалив его из упаковки массива:

$qb->add('where', $qb->expr()->in('r.winner', '?1'));

Эта проблема должна быть исправлена. Возможно, это была проблема в предыдущих версиях Doctrine, но она исправлена ​​в самых последних версиях 2.0.

Ответ 2

Самый простой способ сделать это - связать сам массив как параметр:

$queryBuilder->andWhere('r.winner IN (:ids)')
             ->setParameter('ids', $ids);

Ответ 3

и для завершения строковое решение

$qb->andWhere('foo.field IN (:string)');
$qb->setParameter('string', array('foo', 'bar'), \Doctrine\DBAL\Connection::PARAM_STR_ARRAY);

Ответ 5

Лучший способ сделать это - особенно если вы добавляете несколько условий - это:

$values = array(...); // array of your values
$qb->andWhere('where', $qb->expr()->in('r.winner', $values));

Если ваш массив значений содержит строки, вы не можете использовать метод setParameter со вложенной строкой, потому что ваши кавычки будут экранированы!

Ответ 6

Вот как я его использовал:

->where('b.status IN (:statuses)')
->setParameters([
                'customerId' => $customerId,
                'storeId'    => $storeId,
                'statuses'   => [Status::OPEN, Status::AWAITING_APPROVAL, Status::APPROVED]
            ]);

Ответ 7

Я знаю, что пример OP использует DQL и построитель запросов, но я наткнулся на это, глядя на то, как это сделать с контроллера или вне класса репозитория, поэтому, возможно, это поможет другим.

Вы также можете сделать WHERE IN с контроллера следующим образом:

// Symfony example
$ids    = [1, 2, 3, 4];
$repo   = $this->getDoctrine()->getRepository('AppBundle:RepoName');
$result = $repo->findBy([
    'id' => $ids
]);

Ответ 8

Нашел, как это сделать в 2016 году: https://redbeardtechnologies.wordpress.com/2011/07/01/doctrine-2-dql-in-statement/

Цитата:

Вот как это сделать правильно:

$em->createQuery("SELECT users FROM Entities\User users WHERE users.id IN (:userids)")
->setParameters(array(‘userids’ => $userIds));

Параметр SetParameters будет принимать массив и соответствующим образом развязывать его для использования в инструкции "IN".

Ответ 9

Я предпочитаю:

$qb->andWhere($qb->expr()->in('t.user_role_id', [
    User::USER_ROLE_ID_ADVERTISER,
    User::USER_ROLE_ID_MANAGER,
]));

Ответ 10

Я знаю это старое сообщение, но может быть полезным для кого-то. Я бы проголосовал и усовершенствовал @Daniel Espendiller ответ, обратившись к вопросу, заданному в комментариях о ints

Чтобы сделать эту работу для int правильно, убедитесь, что значения в массиве имеют тип int, вы можете набирать cast to int перед передачей...

 $qb->andWhere('foo.field IN (:ints)');
 $qb->setParameter('ints', array(1, 2), 
 \Doctrine\DBAL\Connection::PARAM_INT_ARRAY);

Протестировано для select/delete в symfony 3.4 & doctrine-bundle: 1.8

Ответ 11

->where($qb->expr()->in('foo.bar', ':data'))
            ->setParameter('participants', $data);

Также работает с:

 ->andWhere($qb->expr()->in('foo.bar', ':users'))
                ->setParameter('data', $data);

Ответ 12

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

Следующие работали для меня:

http://docs.doctrine-project.org/projects/doctrine1/en/latest/en/manual/dql-doctrine-query-language.html#where-clause

->andWhereIn("[fieldname]", [array[]])

Пример данных массива (работает со строками и целыми числами):

$ids = array(1, 2, 3, 4);

Пример запроса (адаптируйте туда, где он вам нужен):

$q = dataTable::getInstance()
    ->createQuery()
    ->where("name = ?",'John')
    ->andWhereIn("image_id", $ids)
    ->orderBy('date_created ASC')
    ->limit(100);

$q->execute();