Wie kann ich ein Array von Zeichenfolgen mit einer vorbereiteten mysqli-Anweisung binden?
Lesezeit: 11 Minuten
Markieren
Ich muss ein Array von Werten an binden WHERE IN(?) Klausel. Wie kann ich das machen?
Das funktioniert:
$mysqli = new mysqli("localhost", "root", "root", "db");
if(!$mysqli || $mysqli->connect_errno)
{
return;
}
$query_str = "SELECT name FROM table WHERE city IN ('Nashville','Knoxville')";
$query_prepared = $mysqli->stmt_init();
if($query_prepared && $query_prepared->prepare($query_str))
{
$query_prepared->execute();
Aber damit kann ich nicht arbeiten bind_param so was:
$query_str = "SELECT name FROM table WHERE city IN (?)";
$query_prepared = $mysqli->stmt_init();
if($query_prepared && $query_prepared->prepare($query_str))
{
$cities = explode(",", $_GET['cities']);
$str_get_cities = "'" . implode("', '", $get_cities) . "'"; // This equals 'Nashville','Knoxville'
$query_prepared->bind_param("s", $cities);
$query_prepared->execute();
Was mache ich falsch?
Ich habe auch versucht call_user_func_arrayaber ich kann anscheinend nicht die richtige Syntax erhalten.
$str_get_cities= "'".implode("','", $get_cities)."'"; . Verwenden Sie keine Anführungszeichen !! Das ist erledigt bind_param mit der Option “s” !
– moskito-x
10. Juli 2013 um 14:14 Uhr
Wie andere empfehlen, verwenden call_user_func_array Funktion, um die erforderlichen Parameter an Ihre parametrisierte Abfrage zu binden. Nur um zu betonen, dass es Parameter akzeptiert, die als Referenz übergeben werden. Ich konnte nur Teile des Codes finden, wie parametrisierte Abfragen mit dynamischer Menge an zu bindenden Parametern ausgeführt werden, also habe ich am Ende meine eigene Funktion gemacht (siehe diesen Beitrag). Es akzeptiert alle parametrisierten SELECT-, UPDATE-, INSERT- und DELETE-Abfragen und hilft mir sehr dabei, jede MySQL-DB-Interaktion in meinem PHP-Code dynamisch auszuführen.
– Mbuster
23. Januar 2017 um 15:16 Uhr
Frühere, klare, vollständige Frage, die genau dasselbe stellt: Verwenden Sie ein Array in einer vorbereiteten mysqli-Anweisung: WHERE .. IN(..) Anfrage
– mickmackusa
3. April 2022 um 4:59 Uhr
Ihr gesunder Menschenverstand
Seit PHP 8.1 können Sie ein Array direkt zur Ausführung übergeben:
Für die früheren Versionen ist die Aufgabe etwas aufwendig, aber machbar. Für einen einfachen Fall, in dem Sie bereits eine Abfrage mit Platzhaltern haben, wäre der Code
$sql = "INSERT INTO users (email, password) VALUES (?,?)"; // sql
$data = [$email, $password]; // put your data into array
$stmt = $mysqli->prepare($sql); // prepare
$stmt->bind_param(str_repeat('s', count($data)), ...$data); // bind array at once
$stmt->execute();
Zuerst müssen wir eine Zeichenfolge mit so vielen erstellen ? markiert, wie viele Elemente sich in Ihrem Array befinden. Dafür würden wir verwenden str_repeat() Funktion, die für den Zweck sehr praktisch ist.
Dann muss dieser String mit Komma-separierten Fragezeichen zur Abfrage hinzugefügt werden. Obwohl es sich um eine Variable handelt, ist sie in diesem Fall sicher, da sie nur konstante Werte enthält
dann muss diese Abfrage wie jede andere Abfrage vorbereitet werden
dann müssen wir einen String mit Typen erstellen, die mit bind_param() verwendet werden sollen. Beachten Sie, dass es normalerweise keinen Grund gibt, unterschiedliche Typen für die gebundenen Variablen zu verwenden – mysql akzeptiert sie alle gerne als Strings. Es gibt Randfälle, aber extrem selten. Für den täglichen Gebrauch können Sie es immer einfach halten und “s” für alles verwenden. str_repeat() ist wieder zur Rettung.
Dann müssen wir unsere Array-Werte an die Anweisung binden. Leider können Sie es nicht einfach so als einzelne Variable schreiben $stmt->bind_param("s", $array)nur skalare Variablen sind erlaubt bind_param(). Zum Glück gibt es eine Argument Entpackoperator das macht genau das, was wir brauchen – sendet ein Array von Werten an eine Funktion, als wäre es eine Menge unterschiedlicher Variablen!
Der Rest ist wie gewohnt – führen Sie die Abfrage aus, erhalten Sie das Ergebnis und rufen Sie Ihre Daten ab!
Der richtige Beispielcode wäre also
$array = ['Nashville','Knoxville']; // our array
$in = str_repeat('?,', count($array) - 1) . '?'; // placeholders
$sql = "SELECT name FROM table WHERE city IN ($in)"; // sql
$stmt = $mysqli->prepare($sql); // prepare
$types = str_repeat('s', count($array)); //types
$stmt->bind_param($types, ...$array); // bind array at once
$stmt->execute();
$result = $stmt->get_result(); // get the mysqli result
$data = $result->fetch_all(MYSQLI_ASSOC); // fetch the data
Obwohl dieser Code ziemlich groß ist, ist er unvergleichlich kleiner als jede andere plausible Lösung, die bisher in diesem Thema angeboten wurde.
Ich verstehe den ersten Absatz Ihrer Antwort nicht. Ich denke nicht, dass eine Frage eine Antwort liefern soll, er sucht eine Antwort, die Sie und andere beantwortet haben. Was ich gesucht habe, war nicht, wie viele Fragezeichen ich hinzufügen muss, die ich bereits hatte. Ich konnte keine richtige Erklärung für bind_param finden, da sich das php.net-Dokument anscheinend nicht darum gekümmert hat. Ich wollte wissen, ob ich ein Array als Parameter übergeben kann.
– AaA
17. April 2020 um 14:00 Uhr
@AaA In meiner Antwort gibt es einen weiteren Absatz, in dem ein Operator zum Entpacken von Argumenten erwähnt wird. hat es deine Frage beantwortet?
– Ihr gesunder Menschenverstand
18. April 2020 um 3:39 Uhr
Danke, das “Argument unpacked operator” war für mich die Antwort. Diese Antwort löst viele andere ähnliche Fragen mit sehr ausgearbeiteten Lösungen.
– Marco Muciño
23. Juli 2020 um 22:02 Uhr
das funktioniert nicht.$stmt->bind_param($paramstring, $params ); Gib mir Array to string conversion jedes Mal
– djack109
31. Dezember 2020 um 17:01 Uhr
moskito-x
Sie können nicht zwei Variablen mit einer binden Fragezeichen!
Für jede Variable, die Sie binden, benötigen Sie eine Fragezeichen.
„bind_param“ prüft jede Variable, ob sie den Anforderungen entspricht. Danach wird der Stringwert in Anführungszeichen gesetzt.
Das wird nicht funktionieren:
"SELECT name FROM table WHERE city IN (?)"; ( becomes too )
$q_prepared->bind_param("s", $cities);
"SELECT name FROM table WHERE city IN ('city1,city2,city3,city4')";
Es muss sein:
"SELECT name FROM table WHERE city IN (?,?,?,?)"; ( becomes too )
$q_prepared->bind_param("ssss", $city1, $city2, $city3, $city4);
"SELECT name FROM table WHERE city IN ('city1', 'city2', 'city3', 'city4')";
$query_prepared->bind_param setzt String-Parameter einzeln in Anführungszeichen. Und die Anzahl der Variablen und die Länge der Zeichenfolgentypen müssen mit den Parametern in der Anweisung übereinstimmen.
$query_str = "SELECT name FROM table WHERE city IN ('Nashville','Knoxville')";
wird werden
$query_str = "SELECT name FROM table WHERE city IN (?,?)";
Jetzt bind_param muss sein
bind_param("ss", $arg1, $arg2)
mit diesem
$query_str = "SELECT name FROM table WHERE city IN (?)";
Und bind_param mit
bind_param("s", $cities)
Du erhältst:
$query_str = "SELECT name FROM table WHERE city IN ('Nashville,Knoxville')";
Deshalb funktioniert ein Array nicht. Die einzige Lösung für diese Tatsache ist call_user_func_array.
Wenn Sie eine Anweisung initialisieren, ist Folgendes nicht erforderlich:
Wenn Sie nicht verwenden möchten call_user_func_array und Sie haben nur eine kleine Anzahl von Argumenten, können Sie dies mit dem folgenden Code tun.
[...]
$cities = explode(",", $_GET['cities']);
if (count($cities) > 3) { echo "too many arguments"; }
else
{
$count = count($cities);
$SetIn = "(";
for($i = 0; $i < $count; ++$i)
{
$code .= 's';
if ($i>0) {$SetIn.=",?";} else {$SetIn.="?";}
}
$SetIn .= ")";
$query_str = "SELECT name FROM table WHERE city IN " . $SetIn;
// With two arguments, $query_str will look like
// SELECT name FROM table WHERE city IN (?,?)
$query_prepared = $mysqli->stmt_init();
if($query_prepared->prepare($query_str))
{
if ($count==1) { $query_prepared->bind_param($code, $cities[0]);}
if ($count==2) { $query_prepared->bind_param($code, $cities[0], $cities[1]);}
if ($count==3) { $query_prepared->bind_param($code, $cities[0], $cities[1], $cities[2]);
// With two arguments, $query_prepared->bind_param() will look like
// $query_prepared->bind_param("ss", $cities[0], $cities[1])
}
$query_prepared->execute();
}
[...]
}
Ich würde vorschlagen, dass Sie es mit versuchen call_user_func_array erreichen.
„Bei der Verwendung von mysqli_stmt_bind_param() in Verbindung mit call_user_func_array() ist Vorsicht geboten. Beachten Sie, dass mysqli_stmt_bind_param() die Übergabe von Parametern als Referenz erfordert, während call_user_func_array() als Parameter eine Liste von Variablen akzeptieren kann, die Referenzen oder Werte darstellen können. ” Quelle -> php.net/manual/en/mysqli-stmt.bind-param.php
Ich hatte auch Probleme damit und habe es zum Laufen gebracht eval bevor Sie herausfinden, dass die meisten Menschen es verwenden call_user_func_array:
$fields = array('model', 'title', 'price'); // Fields in WHERE clause
$values = array( // Type and value for each field
array('s', 'ABCD-1001'),
array('s', '[CD] Test Title'),
array('d', '16.00')
);
$sql = "SELECT * FROM products_info WHERE "; // Start of query
foreach ($fields as $current) { // Build where clause from fields
$sql .= '`' . $current . '` = ? AND ';
}
$sql = rtrim($sql, 'AND '); // Remove last AND
$stmt = $db->prepare($sql);
$types=""; $vals="";
foreach ($values as $index => $current_val) { // Build type string and parameters
$types .= $current_val[0];
$vals .= '$values[' . $index . '][1],';
}
$vals = rtrim($vals, ','); // Remove last comma
$sql_stmt="$stmt->bind_param("" . $types . '",' . $vals . ');'; // Put bind_param line together
eval($sql_stmt); // Execute bind_param
$stmt->execute();
$stmt->bind_result($col1, $col2, $col3, $col4, $col5, $col6); // This could probably also be done dynamically in the same way
while ($stmt->fetch()) {
printf("%s %s %s %s %s %s\n", $col1, $col2, $col3, $col4, $col5, $col6);
}
Erfordert definitiv etwas Spielerei, aber ich mag diese Antwort wirklich sehr. Es kann ein bisschen voluminöser sein als call_user_func_array aber es ist ehrlich gesagt einfacher zu lesen und herauszufinden, was los ist.
– Ethan Moore
20. Juli 2020 um 0:35 Uhr
php 8.2 hat so ziemlich alles mit execute_query gelöst
$this->execute_query($query, $parms);
wie
$query = "SELECT * FROM users WHERE `email` IN (?) LIMIT 1";
$parms = ["[email protected]"];
$this->execute_query($query, $parms);
Erinnern ? ist Platzhalter und Anzahl von ? (Platzhalter) ist die gleiche Zahl wie count($parms) und kann auf verschiedene Arten erfolgen.
In Ihrem Fall sollte es also sein
$query = "SELECT name FROM table WHERE city IN (? , ?)";
$parms = ['Nashville','Knoxville'];
$this->execute_query($query, $parms);
wenn Sie zuerst eine dynamische $Abfrage erstellen möchten, dann
$query = "SELECT name FROM table WHERE city IN (".implode(",",array_map(fn()=>"?",$parms)).")";
Erfordert definitiv etwas Spielerei, aber ich mag diese Antwort wirklich sehr. Es kann ein bisschen voluminöser sein als call_user_func_array aber es ist ehrlich gesagt einfacher zu lesen und herauszufinden, was los ist.
– Ethan Moore
20. Juli 2020 um 0:35 Uhr
Peter Mortensen
So habe ich es gemacht: Bereite die Abfrage mit all ihren separaten Fragezeichen sowie dem Typ String vor.
$cities = array('Nashville', 'Knoxville');
$dibs="";
$query = "SELECT name FROM table WHERE city IN (";
$marks = array();
foreach ($cities as $k => $city) {
// i, s, b, d type based on the variables to bind.
$dibs .= 's';
array_push($marks, '?');
}
$query .= implode(',', $marks) . ')';
Verbinden.
$mysql = new mysqli($host, $user, $pass, $dbname);
$statement =
$mysql->prepare($query)
OR die(sprintf(
'Query error (%s) %s', $mysql->errno, $mysql->error
))
;
Dann verwenden Sie “…” Token / Ellipse (Dokumentation), um das Array zu binden.
if ($statement) {
$statement->bind_param($dibs, ...$cities);
$statement->execute();
$statement->close();
}
$mysql->close();
Ich weiß, dass es irgendwie den Zweck der Bindung zunichte macht, um zu entkommen (aber zumindest funktioniert es gut mit einer Liste von ganzen Zahlen, dh IDs).
14448800cookie-checkWie kann ich ein Array von Zeichenfolgen mit einer vorbereiteten mysqli-Anweisung binden?yes
$str_get_cities= "'".implode("','", $get_cities)."'";
. Verwenden Sie keine Anführungszeichen !! Das ist erledigtbind_param
mit der Option “s” !– moskito-x
10. Juli 2013 um 14:14 Uhr
Wie andere empfehlen, verwenden call_user_func_array Funktion, um die erforderlichen Parameter an Ihre parametrisierte Abfrage zu binden. Nur um zu betonen, dass es Parameter akzeptiert, die als Referenz übergeben werden. Ich konnte nur Teile des Codes finden, wie parametrisierte Abfragen mit dynamischer Menge an zu bindenden Parametern ausgeführt werden, also habe ich am Ende meine eigene Funktion gemacht (siehe diesen Beitrag). Es akzeptiert alle parametrisierten SELECT-, UPDATE-, INSERT- und DELETE-Abfragen und hilft mir sehr dabei, jede MySQL-DB-Interaktion in meinem PHP-Code dynamisch auszuführen.
– Mbuster
23. Januar 2017 um 15:16 Uhr
Frühere, klare, vollständige Frage, die genau dasselbe stellt: Verwenden Sie ein Array in einer vorbereiteten mysqli-Anweisung:
WHERE .. IN(..)
Anfrage– mickmackusa
3. April 2022 um 4:59 Uhr