it-swarm.com.de

Verwendung von WHERE IN mit Doctrine 2

Ich habe den folgenden Code, der mir den Fehler gibt:

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

Code:

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

Daten (oder $ ids):

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

DQL-Ergebnis:

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

Bei der Recherche zu diesem Problem habe ich etwas gefunden, das für alle wichtig ist, die sich mit demselben Problem beschäftigen und nach einer Lösung suchen.

Aus dem ursprünglichen Beitrag die folgende Codezeile:

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

Das Umschließen des benannten Parameters als Array verursacht das Problem der gebundenen Parameternummer. Entfernen Sie es aus seiner Array-Umhüllung:

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

Dieses Problem sollte behoben werden. Dies war möglicherweise in früheren Versionen von Doctrine ein Problem, wurde jedoch in den neuesten Versionen von 2.0 behoben.

101
Buster Neece

Am einfachsten geht das, indem Sie das Array selbst als Parameter binden:

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

und zur Vervollständigung der String-Lösung

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

Ich fand heraus, dass der einzige Weg, um dies zum Laufen zu bringen, wie in den Dokumenten angegeben ist, folgendermaßen aussehen kann:

$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

23
Jeremy Hicks

Ich weiß, dass das Beispiel des OP DQL und den Query Builder verwendet, aber ich bin darüber gestolpert, wie ich es von einem Controller aus oder außerhalb der Repository-Klasse finde. Vielleicht hilft dies anderen.

Sie können auch einen WHERE IN vom Controller auf folgende Weise ausführen:

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

Der beste Weg, dies zu tun - insbesondere, wenn Sie mehr als eine Bedingung hinzufügen - ist:

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

Wenn Ihr Werte-Array Zeichenfolgen enthält, können Sie die setParameter-Methode nicht mit einer implodierten Zeichenfolge verwenden, da Ihre Anführungszeichen mit Escapezeichen versehen werden!

6
ck1

So habe ich es benutzt:

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

Ich weiß, es ist ein alter Beitrag, kann aber für jemanden hilfreich sein. Ich würde die Antwort von @Daniel Espendiller abstimmen und verbessern, indem ich die in den Kommentaren zu Ints gestellten Fragen ansprach

Damit dies für int richtig funktioniert, stellen Sie sicher, dass die Werte in array vom Typ int sind. Sie können vor der Übergabe in int eingeben.

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

Getestet für Auswählen/Löschen in Symfony 3.4 & Doctrine-Bundle: 1.8

5
Azhar Khattak

Wie Sie dies im Jahr 2016 tun können: https://redbeardtechnologies.wordpress.com/2011/07/01/doctrine-2-dql-in-statement/

Zitat:

So machen Sie es richtig:

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

Die setParameters nehmen ein Array und implodieren es ordnungsgemäß, damit es in der IN-Anweisung verwendet werden kann.

4
Calamity Jane

Ich bevorzuge:

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

Ich kämpfte mit demselben Szenario, in dem ich eine Abfrage mit einem Array von Werten durchführen musste.

Folgendes hat für mich gearbeitet:

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

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

Beispiel für Array-Daten (mit Strings und Ganzzahlen gearbeitet):

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

Abfragebeispiel (Anpassen, wo Sie es brauchen):

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

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

Funktioniert auch mit:

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