PDO 与 bindValue 的绑定不起作用
PDO binding with bindValue not working
我第一次尝试在 MySQL 数据库中使用准备好的语句和 PDO。我一直在参考 MySQL 开发人员的 PDO 教程,PHP 数据对象上的 PHP 手册页以及 SO 中涵盖此内容的众多答案,但我无法找到我做错了什么。
具体来说,我无法使用命名占位符。有人可以纠正我吗?
我正在使用的数据库table,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",当到达上面的代码时。 table 中有一条记录对应于用户 2 / 列表 AAAA,但不是检索该记录,而是检索用户 0 的所有记录。如果我将 :user_id 替换为 $user_id,它恢复了正确的用户,但恢复了该用户的所有数据,而不仅仅是 list_name 条记录。
我试过了
$stmt->bindValue(":user_id", (int) trim ($user_id), PDO::PARAM_INT);
但是用户 2 仍然给我用户 0 的记录。我也尝试使用 bindParam,但我认为 bindValue 是我在这种情况下应该使用的。
我在查询后添加了 $stmt->debugDumpParams() ,它显示:
SQL: [23] SELECT * FROM todo_list
Params: 0
我不知道参数 0 是否有帮助。
我使用绑定失败,但我不明白为什么。我 运行 这是 Ubuntu 的最新安装。
我认为你不知何故搞反了。使用绑定参数的正确方法应该是这样的:
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 . ')';
}
我第一次尝试在 MySQL 数据库中使用准备好的语句和 PDO。我一直在参考 MySQL 开发人员的 PDO 教程,PHP 数据对象上的 PHP 手册页以及 SO 中涵盖此内容的众多答案,但我无法找到我做错了什么。
具体来说,我无法使用命名占位符。有人可以纠正我吗?
我正在使用的数据库table,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",当到达上面的代码时。 table 中有一条记录对应于用户 2 / 列表 AAAA,但不是检索该记录,而是检索用户 0 的所有记录。如果我将 :user_id 替换为 $user_id,它恢复了正确的用户,但恢复了该用户的所有数据,而不仅仅是 list_name 条记录。
我试过了
$stmt->bindValue(":user_id", (int) trim ($user_id), PDO::PARAM_INT);
但是用户 2 仍然给我用户 0 的记录。我也尝试使用 bindParam,但我认为 bindValue 是我在这种情况下应该使用的。
我在查询后添加了 $stmt->debugDumpParams() ,它显示:
SQL: [23] SELECT * FROM todo_list
Params: 0
我不知道参数 0 是否有帮助。
我使用绑定失败,但我不明白为什么。我 运行 这是 Ubuntu 的最新安装。
我认为你不知何故搞反了。使用绑定参数的正确方法应该是这样的:
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 . ')';
}