Wie binde ich ein Array von Strings mit einer vorbereiteten mysqli-Anweisung?
Lesezeit: 12 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 das kann ich mit einem bind_param wie diesem nicht zum Laufen bringen:
$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_arraykann aber anscheinend nicht die richtige Syntax abrufen.
$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 um 4:59
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 question mark !
Für jede Variable, die Sie binden, benötigen Sie eine question mark
„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')";
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 einleiten, ist Folgendes nicht erforderlich
wenn Sie nicht verwenden möchten call_user_func_array
und Sie haben nur eine kleine Anzahl von Argumenten
Sie können 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 2 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 2 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
Wenn Sie der Dokumentation weitere Erklärungen und Quellen hinzufügen, wird dies mit Sicherheit akzeptiert! schöne antwort hier!
– Gonaties
27. Mai 2017 um 21:28 Uhr
Das wird nicht funktionieren, alle Parameter müssen Referenzen sein. Sie müssen also das Format wie in definiert haben $format = "siis"; und dann in dem Array, das Sie verwenden &$format. Alle Parameter müssen Referenzen sein.
Erwähnenswert ist auch, dass die Bibliothek jetzt Vorgabe um im Fehlerfall Ausnahmen auszulösen. Vor Version 8.1 war dies nicht der Fall.
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
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). Wenn Sie eine Möglichkeit sehen, diesen Ansatz zu verbessern, können Sie ihn gerne bearbeiten/kommentieren.
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
Jennifer
Dies habe ich getan, nachdem ich die Formulareingaben genauso benannt hatte wie die mysql-Spaltennamen.
$post_fields = array_keys($_POST);
$post_values = array_values($_POST);
$fields_type_i = array("age","age_share","gender_share"); // all mysql col names type int
$fields = ""; // user input fields
$values = ""; // user input vals
$placeholders = ""; // ?,?,?
$params_type = ""; // s=string i=integer
foreach ($post_fields as $field) {
$fields .= "`".$field."`,";
}
for ($i=0;$i<count($post_fields);$i++) { // bind i and s param types
$placeholders .= "?,";
if (in_array($post_fields[$i],$fields_type_i)) {
$params_type .= "i";
} else {
$params_type .= "s";
}
$values .= $post_values[$i];
}
ODER
for ($i=0;$i<count($post_fields);$i++) { // binding only s param type
if (in_array($post_fields[$i],$fields_type_i)) {
$placeholders .= $post_values[$i].",";
} else {
$placeholders .= "?,";
$params_type .= "s";
$values .= $post_values[$i];
}
}
$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 um 4:59