没有为准备好的语句MySQLi PHP中的参数提供数据

时间:2012-09-28 21:06:58

标签: php mysqli

我一直在将我的网站从不受保护的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;
    }

}

此致 哈利

5 个答案:

答案 0 :(得分:4)

您遇到的错误是由于以下几行:

$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();
}

答案 1 :(得分:2)

您使用Zend Framework吗? 它可能是Php和Zend之间的版本问题。 我遇到了PHP 5.3 +的问题,他在使用Zend framework 1.8.3进行插入或更新时遇到了同样的错误。

如果您遇到这种情况,其中一种解决方案是将连接器更改为数据库。试试这个,它对我有用:

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

答案 2 :(得分:0)

“没有为预准备语句中的参数提供数据”意味着声明没有问题,但是您为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)

欢呼声

答案 3 :(得分:0)

我刚刚找到解决同样问题的方法。

这是MySQL过去的一个值,它是NULL。而这个列在表定义中不能是NULL ...

答案 4 :(得分:0)

似乎您可能希望在继续并更新其个人资料之前验证所有这些字段。

if(empty($err)) {

    //Check for UserId, otherwise you can't update a profile
    if (empty($_POST['userid'])) {
        //Handle error here...
        exit;
    }

    $userid = $_POST['userid'];

    //Filter out all NULL values and replace with empty strings (safety first!)
    $username = empty($_POST['username']) ? '' : $_POST['username'];
    $password = empty($_POST['password']) ? '' : $_POST['password'];
    $email = empty($_POST['email']) ? '' : $_POST['email'];
    $usertype = empty($_POST['usertype']) ? '' : $_POST['usertype'];

    $pSETQuery  = '';
    $pSETQuery .= !empty($username) ? ", username = ?" : "";
    $pSETQuery .= !empty($password) ? ", password = ?" : "";
    $pSETQuery .= (!empty($usertype) && $session->isSuperuser()) ? ", usertype = ?" : "";
    //This line stops someone from being able to enter a blank username

    //Prepare statement
    if(!($stmt = $database->prepare("UPDATE user SET email = ? $pSETQuery WHERE UserId = ?"))) {
        $err[] = "PREPARE FAILED.";
    }

    //Bind parameters where appropriate
    $stmt->bind_param("s", $email);
    if(!empty($username)) $stmt->bind_param("s", $username);
    if(!empty($password)) $stmt->bind_param("s", $password);
    if($session->isSuperuser() && !empty($usertype)) $stmt->bind_param("s", $usertype);
    $stmt->bind_param("i", $userid);

    //Execute statement
    if(!$stmt->execute()){
        $err[] = "Execute failed. ERROR: " . $stmt->error;
    }
}