【问题标题】:Parametrized PDO query for LIMIT clauseLIMIT 子句的参数化 PDO 查询
【发布时间】:2018-06-20 17:23:56
【问题描述】:

我已经看到类似问题的回答,但我似乎无法将相同的解决方案应用于我的代码。

$a=1;
$results = DB::query('SELECT posts.`postbody`, posts.`filepost`, posts.`likes`, posts.`posted_at`, users.`id`, posts.`id_of_post` FROM posts, users WHERE posts.`post_id` = users.`id` ORDER BY id_of_post DESC LIMIT :a', array(':a'=>$a));

class DB {
    private static function connect() {
        $pdo = new PDO('mysql:host=127.0.0.1;dbname=SocialNetwork;charset=utf8', 'root', '');
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        return $pdo;
    }
    public static function query($query, $params = array()) {
        $statement = self::connect()->prepare($query);
        $statement->execute($params);
        if (explode(' ', $query)[0] == 'SELECT') {
        $data = $statement->fetchAll();
        return $data;
        }
    }
}

作为记录,以下代码可以正常工作。

$results = DB::query('SELECT posts.`postbody`, posts.`filepost`, posts.`likes`, posts.`posted_at`, users.`id`, posts.`id_of_post` FROM posts, users WHERE posts.`post_id` = users.`id` ORDER BY id_of_post DESC LIMIT 1');

【问题讨论】:

标签: php sql pdo


【解决方案1】:

如果您不定义,如前面的答案所述:

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

您必须将要绑定的参数定义为整数:

foreach($params as $key => $value){
    if(is_numeric($value))
        $statement->bindParam($key,$value,PDO::PARAM_INT);
    else
        $statement->bindParam($key,$value,PDO::PARAM_STR);
}
$statement->execute();

这仍然不是一个完美的解决方案,但如果您信任键值对(即它们来自代码,而不是用户输入)就足够了。

【讨论】:

  • 如何将其绑定为整数?
【解决方案2】:

不理想,但您可以取消 PDO 参数。

$a = 1;
$sql = "SELECT stuff FROM table LIMIT {$a};";

然后从$sql 字符串运行您的查询。

【讨论】:

    【解决方案3】:

    在 MySQL 的 LIMIT 子句中,这样做是错误的:

    LIMIT '1'
    

    因为 LIMIT 必须采用整数,而不是字符串。

    如果 PDO 被配置为模拟 prepare()(通过将值插入到您的 SQL 字符串中),则很可能使插入值成为带引号的字符串,这将导致错误。

    为避免这种情况,您必须使用原生整数作为绑定变量并且您只需指定PDO::PARAM_INT

        $statement = self::connect()->prepare($query);
        $statement->bindParam('a', $a, PDO::PARAM_INT);
        $statement->execute();
    

    这将使驱动程序知道避免在插值周围加上引号。

    如果您将 PDO 属性设置为禁用模拟准备,也可以避免该错误。我总是这样做,因为我不相信“模拟准备”。

    $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
    

    另请参阅我在这里写的测试:Parametrized PDO query and `LIMIT` clause - not working

    【讨论】:

      猜你喜欢
      • 2013-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-28
      相关资源
      最近更新 更多