以下是我的代码快照:
$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
这就是我在看的吗?这个bug从2008年4月就被打开了!在此期间我们该怎么办?
在发送sql语句之前,我需要构建一些分页,并且需要确保数据是干净的,sql注入是安全的。
10条答案
按热度按时间2w2cym1i1#
php的不同版本和pdo的奇怪之处之间有很多不同之处。我尝试了3或4种方法,但无法得到限制工作。
我的建议是在intval()筛选器中使用字符串格式/concatation:
使用intval()防止sql注入非常重要,特别是当您从$get或类似的地方获得限制时。如果你这样做,这是最简单的方式得到限制工作。
有很多关于“pdo中limit的问题”的讨论,但是我的想法是pdo参数从来没有被用于limit,因为它们总是整数一个快速过滤器工作。尽管如此,这还是有点误导,因为哲学一直以来都是自己不做任何sql注入过滤,而是“让pdo来处理”。
anauzrmj2#
既然没有人解释为什么会这样,我就补充一个答案。它这样做的原因是因为你正在使用
trim()
. 如果您查看php手册trim
,返回类型为string
. 然后你就要把它当作PDO::PARAM_INT
. 解决这一问题的方法有:使用
filter_var($integer, FILTER_VALIDATE_NUMBER_INT)
以确保传递的是整数。正如其他人所说,使用
intval()
铸造(int)
检查是否是带is_int()
还有很多方法,但这基本上是根本原因。vtwuwzda3#
查看错误报告,以下内容可能会起作用:
但是你确定你收到的数据是正确的吗?因为在错误消息中,数字后面似乎只有一个引号(而不是用引号括起来的整数)。这也可能是传入数据的错误。你能做点什么吗
print_r($_GET);
想知道吗?ql3eal8s4#
我记得以前有过这个问题。将值强制转换为整数,然后将其传递给bind函数。我想这就解决了。
inb24sb25#
为了
LIMIT :init, :end
你得用那种方法绑起来。如果你有$req->execute(Array());
它不会像它所铸的那样工作PDO::PARAM_STR
数组中的所有变量和LIMIT
你绝对需要一个整数。bindvalue或bindparam。fdx2calv6#
//前(当前错误)$query=“。。。。极限:p1,30;“$stmt->bindparam(':p1',$limiteinferior);
//之后(错误更正)$query=“。。。。极限:p1,30;“$limiteinferior=(int)$limiteinferior$stmt->bindparam(':p1',$limiteinferior,pdo::param\u int);
pftdvrlh7#
bindvalue使用pdo::param_int进行偏移和限制,它将工作
3duebb1j8#
最简单的解决方案是关闭仿真模式。只需添加以下行
此外,在创建pdo连接时,可以将此模式设置为构造函数参数。这可能是一个更好的解决方案,因为有些人报告他们的驱动程序不支持
setAttribute()
功能。它不仅可以解决绑定问题,还可以将值直接发送到
execute()
,这将使您的代码大大缩短。假设已经设置了模拟模式,整个事件将需要多达六行代码ifmq2ha29#
这只是一个总结。
有四个选项可以参数化限制/偏移值:
禁用
PDO::ATTR_EMULATE_PREPARES
如上所述。防止每个
->execute([...])
总是以弦的形式出现。切换到手动
->bindValue(..., ..., PDO::PARAM_INT)
参数填充。但是,它不如->execute list[]方便。
只需在这里做一个例外,并在准备sql查询时插入纯整数。
铸造很重要。更常见的是
->prepare(sprintf("SELECT ... LIMIT %d", $num))
用于这样的目的。如果您不使用mysql,例如sqlite或postgres;也可以直接在sql中强制转换绑定参数。
同样,mysql/mariadb不支持limit子句中的表达式。还没有。
gjmwrych10#
PDO::ATTR_EMULATE_PREPARES
给了我驱动程序不支持此功能:此驱动程序不支持设置属性的错误。
我的解决办法是
$limit
变量作为字符串,然后将其组合到prepare语句中,如下例所示: