Heim  >  Fragen und Antworten  >  Hauptteil

Generieren Sie dynamisch Typdefinitionszeichenfolgen für vorbereitete Anweisungen

Ich schreibe ein Skript, das im Wesentlichen Daten von einer API in eine lokale MySQL-Datenbank lädt. Diese Werte ändern sich je nachdem, was die API zurückgibt.

Bis jetzt funktioniert alles einwandfrei, bis ich versuche, tatsächlich Zeilen in die MySQL-Datenbank einzufügen. Insbesondere weiß ich, dass ich vorbereitete Anweisungen verwenden soll, aber ich habe Probleme, wenn ich versuche, Variablen an vorbereitete Anweisungen zu binden. Wenn ich versuche, den folgenden Code auszuführen, erhalte ich:

PHP Warning:  mysqli_stmt::bind_param(): Number of elements in type definition string doesn't match number of bind variables in /opt/awn2sql/functions.php on line 212

Dies ist der betreffende Code:

$readingValues = array_values($read); //array of just the values in the original array
array_push($readingValues, $devicemac); //add the MAC address of the device that recorded the reading to the array
    
$columns = implode(", ",$readingTypes); //create a string of column names to build the SQL query
    
$valuesCount = count($readingValues); //get a count of the values to fill an array with placeholders
$stmt_placeholders = implode(',',array_fill(0,$valuesCount,'?')); //fill an array with placeholders (i.e. ?,?,?) - see above
$stmt_param = null; //$stmt_param will hold the type definitions string for binding the 
    
foreach ($readingValues as $param) { //iterate through each value in the $readingValues array, get the type, and add it to the type definitions string
    if (gettype($param) == 'integer')
    {
        $stmt_param = $stmt_param.'i';
    }
    else if (gettype($param) == 'double')
    {
        $stmt_param = $stmt_param.'d';
    }               
    else if (gettype($param) == 'string')
    {
    $stmt_param = $stmt_param.'s';
    }
    else if (gettype($param) == 'blob')
    {
        $stmt_param = $stmt_param.'b';
    }
    else
    {
        echo "Invalid data type!";
    }
}

$val_insert_query = "INSERT INTO ".$config['mysql_db'].".readings (".$columns.") VALUES (".$stmt_placeholders.");"; //Template for the query
    
$stmt=$mysqli->prepare($val_insert_query); //Prepares the template for the query for binding, prepared statement becomes $stmt

echo ($stmt_param." (".strlen($stmt_param).")\n"); //for debugging, echo the type definiton string and get its length (which should match the number of values)

echo (count($readingValues)); //count the number of values, which should match the number of elements in the type defintion string
    
$stmt->bind_param($stmt_param, $readingValues); //Binding
    
$stmt->execute(); //execute the statement

Ich gebe offen zu, dass ich in diesem Bereich ein ziemlicher Neuling bin, daher bin ich offen für Vorschläge, wie ich es besser machen kann. Es gibt nie direkte Benutzereingaben, daher mache ich mir über Sicherheitsprobleme relativ keine Sorgen, wenn das irgendeinen Einfluss darauf hat, wie dieses Problem am besten gelöst werden kann.

Vielen Dank im Voraus!

P粉031492081P粉031492081233 Tage vor309

Antworte allen(1)Ich werde antworten

  • P粉702946921

    P粉7029469212024-02-04 14:16:53

    bind_param() 实际上接受变量参数,而不是数组参数。但现代 PHP 具有将数组转换为多个标量参数的语法:

    $stmt->bind_param($stmt_param, ...$readingValues); //Binding

    这相当于将数组元素作为单独的参数传递:

    $stmt->bind_param($stmt_param, $readingValues[0], $readingValues[1],
        $readingValues[2], etc.);

    但是如果您不知道数组中有多少个元素,那就很尴尬了。


    仅供参考,我喜欢使用 PDO 而不是 mysqli。您不必绑定任何内容,只需将值数组作为参数传递给 execute()

    $stmt=$pdo->prepare($val_insert_query); 
    
    $stmt->execute( $readingValues );

    我发现 PDO 更容易。使用 mysqli 的原因是如果您有大量 2000 年代中期的遗留代码需要调整。如果您刚刚开始,则没有旧代码。所以你不妨先采用 PDO。

    有一个很好的 PDO 教程:https://phpdelusions.net/pdo/

    Antwort
    0
  • StornierenAntwort