PHP – Verwenden von PDO mit IN-Klausel-Array

Ich verwende PDO, um eine statement mit einer IN Klausel auszuführen, die ein Array für ihre Werte verwendet:

 $in_array = array(1, 2, 3); $in_values = implode(',', $in_array); $my_result = $wbdb->prepare("SELECT * FROM my_table WHERE my_value IN (".$in_values.")"); $my_result->execute(); $my_results = $my_result->fetchAll(); 

Der obige Code funktioniert einwandfrei, aber meine Frage ist warum dies nicht funktioniert:

  $in_array = array(1, 2, 3); $in_values = implode(',', $in_array); $my_result = $wbdb->prepare("SELECT * FROM my_table WHERE my_value IN (:in_values)"); $my_result->execute(array(':in_values' => $in_values)); $my_results = $my_result->fetchAll(); 

Dieser Code gibt das Element zurück, dessen my_value gleich dem ersten Element in $in_array (1) ist, aber nicht die restlichen Elemente im Array (2 und 3).

Solutions Collecting From Web of "PHP – Verwenden von PDO mit IN-Klausel-Array"

PDO ist mit solchen Dingen nicht gut. Sie müssen eine Zeichenfolge mit Fragezeichen dynamisch erstellen und in Abfrage einfügen.

 $in = str_repeat('?,', count($in_array) - 1) . '?'; $sql = "SELECT * FROM my_table WHERE my_value IN ($in)"; $stm = $db->prepare($sql); $stm->execute($in_array); $data = $stm->fetchAll(); 

Falls andere Platzhalter in der Abfrage vorhanden sind, können Sie den folgenden Ansatz verwenden (der Code stammt aus meinem PDO-Lernprogramm ):

Sie könnten die function array_merge() verwenden, um alle Variablen in einem einzigen Array zusammenzuführen, indem Sie die anderen Variablen in Form von Arrays in der Reihenfolge hinzufügen, in der sie in Ihrer Abfrage erscheinen:

 $arr = [1,2,3]; $in = str_repeat('?,', count($arr) - 1) . '?'; $sql = "SELECT * FROM table WHERE foo=? AND column IN ($in) AND bar=? AND baz=?"; $stm = $db->prepare($sql); $params = array_merge([$foo], $arr, [$bar, $baz]); $stm->execute($params); $data = $stm->fetchAll(); 

Wenn Sie benannte Platzhalter verwenden, wäre der Code etwas komplexer, da Sie eine Sequenz der benannten Platzhalter erstellen müssen, zB :id0,:id1,:id2 . Also wäre der Code:

 // other parameters that are going into query $params = ["foo" => "foo", "bar" => "bar"]; $ids = [1,2,3]; $in = ""; foreach ($ids as $i => $item) { $key = ":id".$i; $in .= "$key,"; $in_params[$key] = $item; // collecting values into key-value array } $in = rtrim($in,","); // :id0,:id1,:id2 $sql = "SELECT * FROM table WHERE foo=:foo AND id IN ($in) AND bar=:bar"; $stm = $db->prepare($sql); $stm->execute(array_merge($params,$in_params)); // just merge two arrays $data = $stm->fetchAll(); 

Glücklicherweise müssen wir für die genannten Platzhalter nicht der strengen Reihenfolge folgen, damit wir unsere Arrays in beliebiger Reihenfolge zusammenführen können.

Die Variablenersetzung in PDO-Prepared-statementen unterstützt keine Arrays. Es ist eins zu eins.

Sie können dieses Problem umgehen, indem Sie basierend auf der Länge des Arrays die Anzahl der benötigten Platzhalter generieren.

 $variables = array ('1', '2', '3'); $placeholders = str_repeat ('?, ', count ($variables) - 1) . '?'; $query = $pdo -> prepare ("SELECT * FROM table WHERE column IN($placeholders)"); if ($query -> execute ($variables)) { // ... } 

Da PDO keine gute Lösung zu bieten scheint, sollten Sie auch die Verwendung von DBAL in Betracht ziehen, die meist der PDO-API folgt, aber auch einige nützliche functionen hinzufügt. http://docs.doctrine-project.org/projects/doctrine-dbal/ de / latest / reference / data-retrieval-and-manipulation.html # Parameterlisten-Konvertierung

 $stmt = $conn->executeQuery('SELECT * FROM articles WHERE id IN (?)', array(array(1, 2, 3, 4, 5, 6)), array(\Doctrine\DBAL\Connection::PARAM_INT_ARRAY) ); 

Es gibt wahrscheinlich einige andere Pakete, die keine Komplexität hinzufügen und die Interaktion mit der database nicht verschleiern (wie die meisten ORMs), aber gleichzeitig kleine typische Aufgaben etwas einfacher machen.

Wie ich es verstehe, liegt es daran, dass PDO den Inhalt von $ in_values ​​als einen einzelnen Gegenstand behandeln wird und es dementsprechend auch tun wird. PDO wird 1,2,3 als eine einzelne Zeichenfolge sehen, so dass die Abfrage ungefähr wie folgt aussieht

SELECT * FROM Tabelle WHERE my_value IN (“1,2,3”)

Sie können denken, dass das Ändern des Implods, um Anführungszeichen und Kommas zu haben, es beheben wird, aber es wird nicht. PDO wird die Anführungszeichen sehen und ändern, wie es die Zeichenfolge zitiert.

Warum Ihre Anfrage mit dem ersten Wert übereinstimmt, habe ich keine Erklärung.

Ich bin gerade auf dieses Problem gestoßen und habe einen kleinen Wrapper programmiert. Es ist nicht der schönste oder beste Code, aber ich denke, es könnte jemandem helfen, also hier ist es:

 function runQuery(PDO $PDO, string $sql, array $params = []) { if (!count($params)) { return $PDO->query($sql); } foreach ($params as $key => $values) { if (is_array($values)) { // get placeholder from array, eg ids => [7,12,3] would be ':ids' $oldPlaceholder = ':'.$key; $newPlaceholders = ''; $newParams = []; // loop through array to create new placeholders & new named parameters for($i = 1; $i < = count($values); $i++) { // this gives us :ids1, :ids2, :ids3 etc $newKey = $oldPlaceholder.$i; $newPlaceholders .= $newKey.', '; // this builds an associative array of the new named parameters $newParams[$newKey] = $values[$i - 1]; } //trim off the trailing comma and space $newPlaceholders = rtrim($newPlaceholders, ', '); // remove the old parameter unset($params[$key]); // and replace with the new ones $params = array_merge($params, $newParams); // amend the query $sql = str_replace($oldPlaceholder, $newPlaceholders, $sql); } } $statement = $PDO->prepare($sql); $statement->execute($params); return $statement; } 

ZB übergibt diese in:

 SELECT * FROM users WHERE userId IN (:ids) array(1) { ["ids"]=> array(3) { [0]=> int(1) [1]=> int(2) [2]=> int(3) } } 

Wird:

 SELECT * FROM users WHERE userId IN (:ids1, :ids2, :ids3) array(3) { [":ids1"]=> int(1) [":ids2"]=> int(2) [":ids3"]=> int(3) } 

Es ist nicht kugelsicher, aber als ein einziger Entwickler für meine Bedürfnisse macht es die Arbeit gut, so weit jedenfalls.