PDOStatement :: bindParam在第一次调用后不起作用

时间:2018-10-14 17:42:41

标签: php sql pdo pdostatement

在编写一个使用PDO连接到数据库的简单类时,我遇到了一些问题。
问题是,在周期中的第一次调用之后,PDOStatement :: bindParam不起作用,我的意思是如果我有两个参数要提供给PDOStatement,则查询不会返回严格的结果,而是如果我只给出一个参数它给出正确的结果。

代码如下:

public function query($sql, $params = NULL) {
        // Opens the PDO connection
        $this->open();

        $this->stmt = $this->pdo->prepare($sql);

        if (isset($params)) {
            foreach ($params as $key => $value) {
                // This doesn't work after the second cicle.
                $this->stmt->bindParam(':' . $key, $value);
            }
        }

        $result = NULL;
        if (!$this->stmt->execute()) {
            $result = false;
        } else {
            $result = $this->stmt->fetchAll();
        }

        // Closes the PDO connection
        $this->close();

        return $result;
}

这是PDOStatement :: debugDumpParams:

SQL: [114]
SELECT 1
FROM   users
WHERE  EXISTS
       (
              SELECT *
              FROM   users
              WHERE  username = :username
              AND    password = :password) limit 1
PARAMS: 2
KEY:NAME: [9] :username paramno=0 NAME=[9] ":username" is_param=1 param_type=2
KEY:NAME: [9] :password paramno=1 NAME=[9] ":password" is_param=1 param_type=2  

感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

TL; DR始终使用bindValue(),除非您想使用bindParam()的特殊行为。

foreach ($params as $key => $value) {
    // This doesn't work after the second cicle.
    $this->stmt->bindParam(':' . $key, $value);
}

之所以无法按预期运行,是因为人们误解了PDO对bindParam()的含义。这并不是说“绑定SQL参数”,而是“将值(即 bindParam()的参数)绑定为引用变量”。因此,在调用execute()时,它将在执行时而不是在调用$value时使用bindParam()的值(绑定到所有SQL参数的变量)。

Cf。 http://php.net/manual/en/pdostatement.bindparam.php解释了此行为。

解决方案是使用bindValue()而不是bindParam()