简体   繁体   中英

I'm trying to go from the soon to be deprecated mysql statements to msqli prepared statements, what am I doing wrong?

Here's my PHP:

    $db = new mysqli($db_host, $db_user, $db_pass, $db_database);

    if (mysqli_connect_errno()) {
        echo "Could not connect to database.";
    }

    // On first connect to database, create a user to hold data for users not logged in
    $stmt = $db->prepare("SELECT id FROM users WHERE id = ?");
    $stmt->bind_param("i" , 1);
    $stmt->execute();

    if ($stmt->num_rows == 0) {
        $stmt = $db->prepare("INSERT INTO users (id, username, email, password) VALUES (?, ?, ?, ?");
        $stmt->bind_param("isss", 1, "anonymous", "anonymous", password_hash("noidentity", PASSWORD_BCRYPT));
        $stmt->execute();
    }

But when it runs, I get this error:

Fatal error: Cannot pass parameter 2 by reference

And it points to the line that I have $stmt->bind_param("i" , 1);

I'm not sure what I'm doing wrong.

Also, if I want to set the value of a field in a row to 1 higher than it currently is, how do I do that with prepared statements?

This, for example: UPDATE users SET wins = wins + 1 WHERE id = ? Setting wins to something is a value, so I assume it should be used with a prepared statement, but do I consider "wins + 1" to be a string, and include that in a prepared statement?

All arguments to bind_param (except the first) must be variables passed by reference, you can't just pass literal values such as 1 , "anonymous" ...

If the values to be inserted are fixed like these, there is no point in using bind_param at all, as it is completely safe to just have them in the query:

$stmt = $bd->prepare("INSERT INTO users (id, username, email, password) VALUES (1, 'anonymous',...)");

However in general you will need to put these parameters into variables, such as:

$params = Array(1,"anonymous","anonymous",password_hash("noidentity",PASSWORD_BCRYPT));
$stmt->bind_param("isss",$params[0],$params[1],$params[2],$params[3]);
$param = 1;
$stmt->bind_param("i" , $param);

Because you cannot pass a value in the bind, only a parameter.

This is why I prefer PDO over Mysqli.

In PDO, you don't need to bind anything, you just pass values to execute() and you can pass them by value so you can use literals and expressions.

$stmt = $pdo->prepare("INSERT INTO users (id, username, email, password) 
    VALUES (?, ?, ?, ?");

$status = $stmt->execute(array(1, "anonymous", "anonymous", 
    password_hash("noidentity", PASSWORD_BCRYPT));

Of course check for success after each prepare() and execute().

This block of code is logically flawed:

if (mysqli_connect_errno()) {
    echo "Could not connect to database.";
}

In the case that there was not an error this function will return 0 aka false , not to mention that this does not cause the script to exit or otherwise skip the query execution. You should change it to something like:

$db = new mysqli($db_host, $db_user, $db_pass, $db_database)
if( $db->connect_error ) {
    echo "Could not connect to database.\n" .
        "Err: " . $db->connect_errno() . "\n" . $db->connect_error();
    // die/exit/return error/throw exception, or...
} else {
    // query prep/execution here
}

You're also mixing OO and procedural calls, I don't know if that's significant or not execution-wise, but it's confusing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM