Как использовать ГДЕ с Doctrine 2 - PullRequest
114 голосов
/ 08 мая 2011

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

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();
}

Данные (или идентификаторы $):

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

Результат DQL:

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

Ответы [ 12 ]

310 голосов
/ 09 августа 2012

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

$queryBuilder->andWhere('r.winner IN (:ids)')
             ->setParameter('ids', $ids);
107 голосов
/ 12 июня 2011

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

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

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

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

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

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

53 голосов
/ 21 мая 2014

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

$qb->andWhere('foo.field IN (:string)');
$qb->setParameter('string', array('foo', 'bar'), \Doctrine\DBAL\Connection::PARAM_STR_ARRAY);
23 голосов
/ 10 мая 2011

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

$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

8 голосов
/ 26 марта 2018

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

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

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

Проверено на выбор / удаление в symfony 3.4 & doctrine-bundle: 1.8

7 голосов
/ 24 января 2017

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

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

// Symfony example
$ids    = [1, 2, 3, 4];
$repo   = $this->getDoctrine()->getRepository('AppBundle:RepoName');
$result = $repo->findBy([
    'id' => $ids
]);
6 голосов
/ 16 июля 2013

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

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

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

5 голосов
/ 09 февраля 2016

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

->where('b.status IN (:statuses)')
->setParameters([
                'customerId' => $customerId,
                'storeId'    => $storeId,
                'statuses'   => [Status::OPEN, Status::AWAITING_APPROVAL, Status::APPROVED]
            ]);
4 голосов
/ 29 февраля 2016

Нашли, как это сделать в 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».

2 голосов
/ 08 февраля 2016

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

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