首頁  >  問答  >  主體

為準備好的語句動態產生類型定義字串

我正在編寫一個腳本,該腳本本質上是將資料從 API 載入到本機 MySQL 資料庫中。這些值會根據 API 傳回的內容而變化。

到目前為止,一切都工作正常,直到我嘗試將行實際插入 MySQL 資料庫。具體來說,我知道我應該使用準備好的語句,但是當我嘗試將變數綁定到準備好的語句時遇到了麻煩。當我嘗試運行以下程式碼時,我得到:

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

這是有問題的程式碼:

$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

我坦率地承認我在這方面有點新手,所以我願意接受任何關於如何做得更好的建議。就其價值而言,從來沒有任何直接的用戶輸入,所以我相對不關心安全問題,如果這對如何最好地解決這個問題有影響的話。

提前致謝!

P粉031492081P粉031492081282 天前351

全部回覆(1)我來回復

  • 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/

    #

    回覆
    0
  • 取消回覆