如何在 LIMIT 子句中应用 bindValue 方法?

2022-08-30 07:10:16

以下是我的代码的快照:

$fetchPictures = $PDO->prepare("SELECT * 
    FROM pictures 
    WHERE album = :albumId 
    ORDER BY id ASC 
    LIMIT :skip, :max");

$fetchPictures->bindValue(':albumId', $_GET['albumid'], PDO::PARAM_INT);

if(isset($_GET['skip'])) {
    $fetchPictures->bindValue(':skip', trim($_GET['skip']), PDO::PARAM_INT);    
} else {
    $fetchPictures->bindValue(':skip', 0, PDO::PARAM_INT);  
}

$fetchPictures->bindValue(':max', $max, PDO::PARAM_INT);
$fetchPictures->execute() or die(print_r($fetchPictures->errorInfo()));
$pictures = $fetchPictures->fetchAll(PDO::FETCH_ASSOC);

我得到

您的 SQL 语法中存在错误;检查与您的MySQL服务器版本相对应的手册,以获取在第1行的“15”,15“附近使用正确的语法

似乎PDO正在SQL代码的LIMIT部分中向我的变量添加单引号。我查了一下,我发现了这个错误,我认为它是相关的:http://bugs.php.net/bug.php?id=44639

这就是我所看到的吗?此错误自2008年4月以来一直打开!在此期间,我们应该怎么做?

我需要构建一些分页,并且需要在发送sql语句之前确保数据干净,sql注入安全。


答案 1

我记得以前遇到过这个问题。将值强制转换为整数,然后再将其传递给绑定函数。我认为这解决了它。

$fetchPictures->bindValue(':skip', (int) trim($_GET['skip']), PDO::PARAM_INT);

答案 2

最简单的解决方案是关闭仿真模式。您只需添加以下行即可完成此操作

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

此外,在创建 PDO 连接时,可以将此模式设置为构造函数参数。这可能是一个更好的解决方案,因为有些人报告说他们的驱动程序不支持该功能。setAttribute()

它不仅可以解决绑定问题,还可以让您直接将值发送到 中,这将使您的代码大大缩短。假设仿真模式已经设置好了,整个事情将需要多达六行代码。execute()

$skip = isset($_GET['skip']) ? (int)trim($_GET['skip']) : 0;
$sql  = "SELECT * FROM pictures WHERE album = ? ORDER BY id LIMIT ?, ?";
$stmt  = $PDO->prepare($sql);
$stmt->execute([$_GET['albumid'], $skip, $max]);
$pictures = $stmt->fetchAll(PDO::FETCH_ASSOC);

推荐