Как использовать 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')
Ответы
Ответ 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);
Ответ 4
Я обнаружил, что, несмотря на то, что указывают документы, единственный способ заставить это работать:
$ids = array(...); // Array of your values
$qb->add('where', $qb->expr()->in('r.winner', $ids));
http://groups.google.com/group/doctrine-dev/browse_thread/thread/fbf70837293676fb
Ответ 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();