我正在学习PDO,并发现确保我的语句正常工作很棘手。我有一个PHP函数,只需将数字1添加到总数中即可更新我的数据库。
function add_rating($place_id,$rating_id) {
//make $db accessible inside the function
global $db;
// query v1
$sql = "UPDATE places_ratings SET ? +1 WHERE place_id=?";
$q = $db->prepare($sql);
$q->execute(array($rating_id,$place_id));
}
我试过这个变种,我都无法开始工作。我不知道我是否使用了错误的问号。我关注的是this guide,还有previous SO question。最后我尝试了第一次使用的不同方法,所以我很想重复使用它,因为它看起来也简单得多。
function add_rating($place_id,$rating_id) {
//make $db accessible inside the function
global $db;
// query v2
$query = "UPDATE places_ratings SET $rating_id = ($rating_id +1) WHERE place_id = $place_id";
$update = $db->query($query);
}
我的问题是:哪个陈述更好/更安全?其次,第一个带问号的版本我做错了什么?感谢...
答案 0 :(得分:2)
准备好的陈述不就像将变量复制到一段文本中一样。准备好的语句在查询逻辑和查询应该处理的值之间分开。他们在那里,所以你能够告诉你的数据库“你应该这样做”,让数据库理解它,然后给它应该做的事情。逻辑本身不可变,它需要在第一次完成。
因此,您只能使用占位符来表示值。您的查询需要阅读UPDATE ... SET FIELD = VALUE WHERE FIELD = VALUE
。 FIELD
部分需要在声明中,VALUE
部分可以使用占位符。看起来您的$rating_id
变量是变量字段名称。首先,这是个坏主意。如果可能,您不应该使字段名称变量。但是如果必须,您不能为它们使用预准备语句占位符。相反,你必须这样做:
$rating_id = 'field_name';
$query = "UPDATE places_ratings SET `$rating_id` = `$rating_id` + 1 WHERE `place_id` = ?";
$stmt = $db->prepare($query);
$stmt->execute(array($place_id));
由您决定$rating_id
是否安全且包含已知的白名单值。不要让用户以任何方式为其提供价值。
答案 1 :(得分:1)
请了解prepared statements是什么。而且你也可以使用tutorial,它不会促进不良做法和易受攻击的代码。
正确创建和使用的预准备语句将始终比连接查询字符串更安全,因为预处理语句单独发送查询逻辑和数据。
此外,如果您使用的是PDO,那么通常使用bindParam()
方法优先于将execute()
方法中的值直接作为数组传递。这是因为,当在execute()
中传递值时,值将绑定为PDO::PARAM_STR
,即使DB列需要和整数。
P.S。 在代码中停止使用 global
!!
答案 2 :(得分:1)
在第一个示例中,一般准备好的语句更安全,因为它们不受SQL注入的影响。
您的示例不起作用,因为您无法在预准备语句中使用?
参数指定字段名称。即使你的SQL仍然可能出错,这也会扩展到
UPDATE places_ratings SET whatever +1 WHERE place_id=?
无效。
如果您的$rating_id
是在代码中生成的而不是从用户输入中获取的,那么您可以将这两种方法结合起来。