简体   繁体   English

使用关联数组在PHP中使用PDO准备语句会产生错误的结果

[英]PDO prepared statement in PHP using associative arrays yields wrong results

I am working on a very small PHP and MySQL application. 我正在开发一个非常小的PHP和MySQL应用程序。 I have a class called User for manipulating user data in the database which contains a createUser method as shown below:- 我有一个名为User的类,用于在数据库中操作用户数据,其中包含一个createUser方法,如下所示: -

/**
* Creates a new user record in the users table for a new user
*   
* @return void
*/
public function createUser($user_id, $user_name, $location_id) {

    // query to execute
    $query = "INSERT INTO 
                      users(user_id,user_name,location_id)
                      VALUES(:id,:name,:location)";

    // query parameters
    $parameters = array (
        ':id' => $user_id,
        ':name' => $user_name,
        ':location' => $location_id
    );

    $databaseInteractions = new DatabaseInteractions();
    $databaseInteractions->executeUpdate($this->_connection, $query, $parameters);

}

I have another class that will contain common methods for interacting with the database called DatabaseInteractions as shown in the above code. 我有另一个类,它将包含与数据库交互的常用方法,名为DatabaseInteractions,如上面的代码所示。 This class contains a method called executeUpdate for executing DML queries as shown below:- 该类包含一个名为executeUpdate的方法,用于执行DML查询,如下所示: -

/**
 * A function for executing DML queries using a prepared statement
 * @param $connection The database connection object
 * @param $query The dml query to be executed
 * @param $parameters The input parameters for the query as a hash 
 */
public function executeUpdate($connection,$query, $parameters) {

    if ($stmt = $connection->prepare($query)) {

        //bind query parameters
        foreach ($parameters as $key => $value) {
            $stmt->bindParam($key, $value);
        }
        //begin transaction
        $connection->beginTransaction();

        $stmt->execute();
        $stmt->closeCursor();

        //commit transaction
        $connection->commit();
    }
}    

When i call the createUser method in the User class as shown below, 当我在User类中调用createUser方法时,如下所示,

$user->createUser(3,"NewUser",1);

The values inserted in the database are as follows:- 插入数据库的值如下: -

   user_id   user_name  location_id
    1              1             1

I spent some time debugging the code but still can't seem to find the reason why this is happening. 我花了一些时间调试代码,但似乎仍然无法找到发生这种情况的原因。 user_id is the PK and is an int. user_id是PK,是一个int。 user_name is varchar and location_id is FK and is int. user_name是varchar,location_id是FK,是int。

I am a Java developer and new to PHP so any inputs related to php naming conventions, coding standards, etc are always welcome. 我是一名Java开发人员,也是PHP的新手,所以任何与php命名约定,编码标准等相关的输入都是受欢迎的。

Answer: reference semantics gotcha. 答案:参考语义陷阱。

The second parameter of bindParam is passed by reference: bindParam的第二个参数通过引用传递:

Binds a PHP variable to a corresponding named or question mark placeholder in the SQL statement that was use to prepare the statement. 将PHP变量绑定到用于准备语句的SQL语句中的相应命名或问号占位符。 Unlike PDOStatement::bindValue(), the variable is bound as a reference and will only be evaluated at the time that PDOStatement::execute() is called. 与PDOStatement :: bindValue()不同,变量被绑定为引用,并且仅在调用PDOStatement :: execute()时进行计算。

Therefore, when the statement is executed all three parameters will evaluate to whatever the last value of $value was -- in this case, 1 . 因此,当执行语句时,所有三个参数都将计算为$value的最后一个值 - 在本例中为1

To solve the problem, use the optional parameter of execute instead of explicitly binding the parameters: 要解决此问题,请使用execute的可选参数,而不是显式绑定参数:

public function executeUpdate($connection,$query, $parameters) {
    if ($stmt = $connection->prepare($query)) {
        $connection->beginTransaction();

        $stmt->execute($parameters);
        $stmt->closeCursor();

        //commit transaction
        $connection->commit();
    }
}    

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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