Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No data supplied for parameters in MySQLi prepared statement

Tags:

php

mysqli

I've been reworking my website from unprotected MySQL queries to mysqli prepared statements and it all went well until I got this: No data supplied for parameters in prepared statement.

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;
    }

}
like image 475
PwnageAtPwn Avatar asked Sep 28 '12 21:09

PwnageAtPwn


People also ask

Which function is used in Mysqli with prepared statements?

$stmt->bind_param("sss", $firstname, $lastname, $email); This function binds the parameters to the SQL query and tells the database what the parameters are. The "sss" argument lists the types of data that the parameters are.

What is Mysqli prepare?

Definition and Usage. The mysqli_prepare() function prepares an SQL statement for execution, you can use parameter markers ("?") in this query, specify values for them, and execute it later.

What is Mysqli STMT?

" $stmt " obviously (I think) stands for "statement". As a variable name it's arbitrary, you can name that variable anything you want. $stmt is just rather idiomatic. A prepared statement as such is a database feature.


1 Answers

The error you are getting is becauses of these lines:

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

You can only call bind_param() once and you need to provide the exact number of values as you have placeholders in the SQL. This function is not well designed, which is one of the main reasons people prefer PDO.

To solve the problem you need to dynamically prepare 3 things: placeholders, types and variables to bind. Here is how you could dynamically build such query:

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();
}
like image 152
Dharman Avatar answered Sep 23 '22 00:09

Dharman