与bindValue绑定的PDO不起作用

时间:2015-04-05 16:51:41

标签: php mysql pdo

我正在尝试使用MySQL数据库首次使用预准备语句和PDO。我一直在提到MySQL开发人员的PDO教程,关于PHP数据对象的PHP手册页以及SO中的大量答案,但我无法找到我做错的事。

具体来说,我不能让命名占位符起作用。有人可以把我弄好吗?

我正在使用的数据库表,t_list是

  `user_id` mediumint(8) unsigned NOT NULL,
  `list_name` char(30) NOT NULL,
  `list_items` longtext NOT NULL,
  `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`user_id`,`list_name`)

直接在SQL中使用变量的不安全方法有效......

if ($tableName=="t_list") {
    try {
        $stmt = $db->prepare("SELECT * FROM t_list");
        $stmt->bindValue(":user_id", $user_id, PDO::PARAM_INT);
        $stmt->bindValue(":list_name", $list_name, PDO::PARAM_STR);
        $stmt->execute();
        foreach($db->query("SELECT `list_items` FROM t_list WHERE user_id=$user_id AND list_name='$list_name'") as  $row) {
            $found = 1;
            echo $row['list_items'];
        }    
        $stmt->debugDumpParams();
    } catch(PDOException $e) {
        echo "An error occured reading 't_list' table!"; 
        echo $e->getMessage();                   
    }
    if ($found==0) { 
        echo "read failed : " . $user_id . " / " . $list_name . " not found:"; 
    } 
} else {
    echo 'tableName not recognized (' . $tableName . ')';
}

...但我认为我应该做的是使代码安全:

foreach($db->query("SELECT `list_items` FROM t_list WHERE user_id=:user_id AND list_name=:list_name") as  $row) {    

正如另一个SO回答中所建议的,我先做到了这一点:

    $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

没有MySQL或PHP错误消息。

会发生什么:

当达到上面的代码时,假设$ user_id中的值为2,$ list_name为“AAAA”。表中有一条记录对应于用户2 /列表AAAA,但它不是检索那条记录,而是检索用户0的所有记录。如果我用$ user_id替换:user_id,它将恢复正确的用户,但是所有数据都是该用户,而不仅仅是一个list_name记录。

我试过

$stmt->bindValue(":user_id", (int) trim ($user_id), PDO::PARAM_INT);

但对于仍然给我用户0的记录的用户2。我也尝试使用bindParam,但我认为在这种情况下我应该使用bindValue。

我在查询后添加了$ stmt-> debugDumpParams()并显示:

SQL: [23] SELECT * FROM todo_list
Params:  0

我不知道Params 0是否是一个有用的指示。

我对绑定的使用失败了,但我看不出原因。我在最新的Ubuntu安装上运行它。

1 个答案:

答案 0 :(得分:1)

我想你不知何故倒退了。使用绑定参数的正确方法应该是这样的:

if ($tableName=="t_list") {
    try {
        $stmt = $db->prepare("SELECT * FROM t_list WHERE user_id=:user_id and list_name=:list_name");
        $stmt->bindValue(":user_id", $user_id, PDO::PARAM_INT);
        $stmt->bindValue(":list_name", $list_name, PDO::PARAM_STR);
        $stmt->execute();
        $rows = $stmt->fetchAll();
        foreach($rows as  $row) {
            $found = 1;
            echo $row['list_items'];
        }    
        $stmt->debugDumpParams();
    } catch(PDOException $e) {
        echo "An error occured reading 't_list' table!"; 
        echo $e->getMessage();                   
    }
    if ($found==0) { 
        echo "read failed : " . $user_id . " / " . $list_name . " not found:"; 
    } 
} else {
    echo 'tableName not recognized (' . $tableName . ')';
}