Cómo usar WHERE IN con Doctrine 2

Tengo el siguiente código que me da el error:

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

Código:

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

Datos (o $ ids):

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

Resultado DQL:

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

Al investigar este tema, encontré algo que será importante para cualquiera que se encuentre con este mismo problema y busque una solución.

Desde la publicación original, la siguiente línea de código:

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

Al envolver el parámetro nombrado como una matriz, se genera el número de parámetro vinculado. Al eliminarlo de su envoltura de matriz:

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

Este problema debe ser arreglado. Esto podría haber sido un problema en versiones anteriores de Doctrine, pero se corrigió en las versiones más recientes de 2.0.

La forma más fácil de hacerlo es vinculando la matriz en sí misma como un parámetro:

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

y para completar la solución de cadena

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

Descubrí que, a pesar de lo que indican los documentos, la única forma de hacer que esto funcione es así:

 $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

La mejor forma de hacerlo, especialmente si agrega más de una condición, es:

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

Si su matriz de valores contiene cadenas, no puede usar el método setParameter con una cadena implosionada, ¡porque sus presupuestos se escaparán!

Así es como lo usé:

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

Encontré cómo hacerlo en el año de 2016: https://redbeardtechnologies.wordpress.com/2011/07/01/doctrine-2-dql-in-statement/

Citar:

Aquí es cómo hacerlo correctamente:

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

SetParameters tomará una matriz y la implota correctamente para ser utilizada en la instrucción “IN”.

Sé que el ejemplo de OP es el uso de DQL y el generador de consultas, pero me encontré con esto buscando cómo hacerlo desde un controlador o fuera de la clase de repository, así que tal vez esto ayude a otros.

También puede hacer un WHERE IN el controlador de esta manera:

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

Yo prefiero:

 $qb->andWhere($qb->expr()->in('t.user_role_id', [ User::USER_ROLE_ID_ADVERTISER, User::USER_ROLE_ID_MANAGER, ])); 
 ->where($qb->expr()->in('foo.bar', ':data')) ->setParameter('participants', $data); 

También trabaja con:

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

Luché con este mismo escenario donde tuve que hacer una consulta en una matriz de valores.

Lo siguiente funcionó para mí:

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

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

Ejemplo de datos de matriz (trabajado con cadenas y enteros):

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

Ejemplo de consulta (adáptese donde lo necesite):

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