开发者

Can't pass a constant variable by reference with $stmt->bind_param()?

开发者 https://www.devze.com 2023-03-08 20:04 出处:网络
This is my code snippet: private function add_user_limit() { global $mysqli; $stmt = $mysqli->prepare(\"INSERT INTO `user_limits` (user_ip, downloads_left) VALUES (?, ?)\");

This is my code snippet:

private function add_user_limit()
{
    global $mysqli;
    $stmt = $mysqli->prepare("INSERT INTO `user_limits` (user_ip, downloads_left) VALUES (?, ?)");
    $stmt->bind_param("si", $this->user_ip, DEFAULT_USER_LIMIT);
    $stmt->execute();
    if($stmt->affected_rows == 0)
        throw new Exception("Couldn't add new user to the user_limits table");
    $stmt->close();
    $this->downloads_left = DEFAULT_USER_LIMIT;
}

DEFAULT_USER_LIMIT is defined as 8, but with the above code I get this error:

Fatal error: Cannot pass p开发者_运维问答arameter 3 by reference in C:\xampp\htdocs\classes\limits.class.php on line 38

But if I do this:

private function add_user_limit()
{
    global $mysqli;
    $stmt = $mysqli->prepare("INSERT INTO `user_limits` (user_ip, downloads_left) VALUES (?, ?)");
    $user_limit = DEFAULT_USER_LIMIT; // For some reason we can't pass a constant to bind_param
    $stmt->bind_param("si", $this->user_ip, $user_limit);
    $stmt->execute();
    if($stmt->affected_rows == 0)
        throw new Exception("Couldn't add new user to the user_limits table");
    $stmt->close();
    $this->downloads_left = DEFAULT_USER_LIMIT;
}

It works. I was just wondering why this happens, as it doesn't really make sense to me. I don't see any reason why bind_param() can't take a constant variable as a parameter.

Thanks!


Quite simply, it's because you can't pass a constant by reference, and there would be no point in doing so, as it is immutable. Constants, by the way, are not variables; it's right there in the name.


Mysqli's bind_param is defined like this:

bind_param ( string $types , mixed &$var1 [, mixed &$... ] )

Explanation

& means that variable is passed by reference and because constants (e.g.DEFAULT_USER_LIMIT) in PHP can not be referenced this way, they can only be passed as values because that's what they are.

So if you have a function that enforces passing by reference, first you must store the value of the constant to a variable and pass the variable (as you did...)

Modern solution - just use PDO

If you can use PDO interface and don't need to pass values by reference,
just use PDO's bindValue() + PDO in common cases is used almost the same way as Mysqli.

public bool PDOStatement::bindValue ( mixed $parameter , mixed $value [, int $data_type = PDO::PARAM_STR ] )

And if you'd still need to pass by reference, PDO also has a bindParam()

public bool PDOStatement::bindParam ( mixed $parameter , mixed &$variable [, int $data_type = PDO::PARAM_STR [, int $length [, mixed $driver_options ]]] )


The following things can be passed by reference:

  • Variables, i.e. foo($a)
  • New statements, i.e. foo(new foobar())
  • References returned from function

No other expressions should be passed by reference, as the result is undefined

http://php.net/manual/en/language.references.pass.php

additionally,

mysqli_stmt_bind_param() requires parameters to be passed by reference, whereas call_user_func_array() can accept as a parameter a list of variables that can represent references or values.

http://php.net/manual/en/mysqli-stmt.bind-param.php

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号