簡體   English   中英

沒有為 MySQLi 准備好的語句中的參數提供數據

[英]No data supplied for parameters in MySQLi prepared statement

我一直在將我的網站從不受保護的 MySQL 查詢改造成 mysqli 准備好的語句,一切都很順利,直到我得到這個:沒有為准備好的語句中的參數提供數據。

if(empty($err)) {
    $pSETQuery  = NULL;
    if(!empty($_POST['password'])) {
        $pSETQuery .= ", password = ?";
    }
    if($session->isSuperuser()) {
        $pSETQuery .= ", usertype = ?";
    }
    if(!($stmt = $database->prepare("UPDATE user SET username = ?, email = ? $pSETQuery WHERE UserId = ?"))) {
        $err[] = "PREPARE FAILED.";
    }
    $stmt->bind_param("s", $_POST['username']);
    $stmt->bind_param("s", $_POST['email']);
    if(!empty($_POST['password'])) {
        $stmt->bind_param("s", $_POST['password']);
    }
    if($session->isSuperuser()) {
        $stmt->bind_param("s", $_POST['usertype']);
    }
    $stmt->bind_param("i", $_POST['userid']);
    if(!$stmt->execute()){
        $err[] = "Execute failed. ERROR: " . $stmt->error;
    }

}

你得到的錯誤是因為這些行:

$stmt->bind_param("s", $_POST['username']);
$stmt->bind_param("s", $_POST['email']);

您只能調用一次bind_param()並且您需要提供確切數量的值,因為您在 SQL 中有占位符。 這個功能設計得不好,這也是人們偏愛 PDO 的主要原因之一。

要解決這個問題,您需要動態准備 3 件事:占位符、類型和要綁定的變量。 以下是動態構建此類查詢的方法:

if(empty($err)) {
    $pSETQuery  = '';
    $types = 'sss'; // for the three constant placeholders
    $data = [$_POST['username'], $_POST['email']];
    if(!empty($_POST['password'])) {
        $pSETQuery .= ", password = ?";
        $types .= 's'; //concat one more
        $data[] = $_POST['password'];
    }
    if($session->isSuperuser()) {
        $pSETQuery .= ", usertype = ?";
        $types .= 's'; //concat one more
        $data[] = $_POST['usertype'];
    }
    $data[] = $_POST['userid']; // for UserId
    
    $stmt = $database->prepare("UPDATE user SET username = ?, email = ? $pSETQuery WHERE UserId = ?");
    $stmt->bind_param($types, ...$data);
    $stmt->execute();
}

你使用 Zend 框架嗎? 這可能是 Php 和 Zend 之間的版本問題。 我遇到了 PHP 5.3 + 的問題,他們在使用 Zend 框架 1.8.3 插入或更新時遇到了同樣的錯誤。

如果是這種情況,解決方案之一是更改連接到數據庫的連接器。 試試這個,它對我有用:

$db = new Zend_Db_Adapter_Pdo_Mysql(array(
    'host'     => '127.0.0.1',
    'username' => 'webuser',
    'password' => 'xxxxxxxx',
    'dbname'   => 'test'
));

“未為准備好的語句中的參數提供數據”表示語句沒問題,但您提供給 bind_param 的變量中至少有一個不符合預期! 我會打印出 $_POST 並查看發生了什么並最終設置 $pSETQuery = ''; 並且不為空!

$_POST['username']
$_POST['email']
$_POST['password']
$_POST['usertype']
$_POST['userid'] // this one is the one I would really watch after, how do you tell the userid if the user is not logged ( i assume that from email, passwrod and might be wrong)

我剛剛找到了解決同樣問題的方法。

這是一個傳遞給 MySQL 的值,即NULL 而此列在表定義中不能為NULL ...

我一直在將網站從不受保護的MySQL查詢改寫為mysqli准備好的語句,直到我得到為止,一切都進行得很順利:在准備好的語句中沒有為參數提供任何數據。

if(empty($err)) {
    $pSETQuery  = NULL;
    if(!empty($_POST['password'])) {
        $pSETQuery .= ", password = ?";
    }
    if($session->isSuperuser()) {
        $pSETQuery .= ", usertype = ?";
    }
    if(!($stmt = $database->prepare("UPDATE user SET username = ?, email = ? $pSETQuery WHERE UserId = ?"))) {
        $err[] = "PREPARE FAILED.";
    }
    $stmt->bind_param("s", $_POST['username']);
    $stmt->bind_param("s", $_POST['email']);
    if(!empty($_POST['password'])) {
        $stmt->bind_param("s", $_POST['password']);
    }
    if($session->isSuperuser()) {
        $stmt->bind_param("s", $_POST['usertype']);
    }
    $stmt->bind_param("i", $_POST['userid']);
    if(!$stmt->execute()){
        $err[] = "Execute failed. ERROR: " . $stmt->error;
    }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM