1

我正在学习 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));   

}

我尝试了这种变体,但我都无法开始工作。我不知道我是不是用错了问号。我正在关注本指南以及之前的 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);

}

我的问题是:哪种说法更好/更安全?其次,我对带有问号的第一个版本做错了什么?谢谢...

4

3 回答 3

2

准备好的语句不仅仅是将变量复制粘贴到一段文本中。准备好的语句将查询逻辑和查询应该处理的值分开。它们在那里,所以你可以告诉你的数据库“你应该这样做”,让数据库理解它,然后给它应该用它做某事的值。逻辑本身不能是可变的,它需要在第一次完成。

因此,您只能对值使用占位符。您的查询需要阅读UPDATE ... SET FIELD = VALUE WHERE FIELD = VALUEFIELD部分需要在声明中,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安全并包含已知的白名单值。不要让用户以任何方式为其提供价值。

于 2012-08-18T07:50:44.577 回答
2

一般来说,第一个示例中的准备好的语句更安全,因为它们不受 SQL 注入的影响。

您的示例不起作用,因为您无法?在准备好的语句中使用参数指定字段名称。即使您的 SQL 仍然是错误的,这也会扩展到

 UPDATE places_ratings SET whatever +1 WHERE place_id=?

这是无效的。

如果您$rating_id是在代码中生成的,而不是从用户输入中获取的,则可以将这两种方法结合起来。

于 2012-08-18T07:55:56.773 回答
1

请去了解准备好的陈述是什么。而且您还可以使用不会宣传不良做法和易受攻击的代码的教程。

正确创建和使用的预处理语句总是比连接查询字符串更安全,因为预处理语句分别发送查询逻辑和数据。

此外,如果您使用的是 PDO,那么通常bindParam()应该优先使用方法,而不是直接在execute()方法中将值作为数组传递。这是因为,当在 中传递值时execute(),这些值被绑定为PDO::PARAM_STR,即使 DB 列期望为整数。

PS停止 global 在您的代码中使用!

于 2012-08-18T07:47:54.913 回答