我是靠谱客的博主 专一蜻蜓,最近开发中收集的这篇文章主要介绍PHP中PDO数据访问对象处理LIMIT子句的一处BUG,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

近期的项目中,数据访问层类使用了PDO作为底层,PDO相比mysql_*系列函数具有更高的性能和安全性。在使用时却发现了PDO对象处理带有LIMIT子句的SQL语句时,不能正确处理LIMIT子句中的占位符。例如:

$sql = "SELECT * FROM user LIMIT ?, ?";
$stmt = $pdo->prepare($sql);
$stmt->execute(array(0, 20));
....

在这段代码中,按照PDO文档的说法,两个问号的位置将会被0, 20这两个参数填充,并且类型将会使用和参数类型相匹配的PDO数据类型。但是执行这条语句却返回一个空集合。

var_dump($stmt->fetchAll());
// 输出 empty

然而将问号的位置直接填写数字,是可以正常取得20条记录的。

在谷歌上搜索发现,有其他人也遇到了同样的BUG:

http://stackoverflow.com/questions/5508993/pdo-limit-and-offset

http://stackoverflow.com/questions/2269840/php-pdo-bindvalue-in-limit

http://bbs.phpchina.com/thread-149339-1-1.html

关于这一Bug,可以在PHP官方的Bug Report平台找到:

https://bugs.php.net/bug.php?id=44639

解决的方法是,使用bindValue方法绑定值到SQL语句,并且指定第三个参数为INT类型:

$sql = "SELECT * FROM user LIMIT ?, ?";
$stmt = $pdo->prepare($sql);
$stmt->bindValue(1, 0, PDO::PARAM_INT);
$stmt->bindValue(2, 20, PDO::PARAM_INT);
$stmt->execute();

这样再次执行,发现20条记录被正确地查询出来。

不过这样不算完美解决,我们通常会对PDO对象进行一些封装才使用,比如构建一次查出来SQL语句并返回结果集数组的方法,传参是不能用bindValue的。于是我写了一个用于自动选择类型的函数:

function select_datatype($val) {
if (is_bool($val)) {
return PDO::PARAM_BOOL;
} elseif (is_int($val)) {
return PDO::PARAM_INT;
} elseif {is_null($val)) {
return PDO::PARAM_NULL;
} else {
return PDO::PARAM_STR;
}
}

这样将$stmt->execute(array(0, 20));类似的语句,转换为循环遍历使用bindValue()绑定值,并使用select_datatype()选择类型即可解决这一问题。

其实早在2008年,就有人向PHP官方报告了这个Bug,但是至今仍未被Fix。如果之后有时间,研究研究能不能做个针对这个问题的补丁。

最后

以上就是专一蜻蜓为你收集整理的PHP中PDO数据访问对象处理LIMIT子句的一处BUG的全部内容,希望文章能够帮你解决PHP中PDO数据访问对象处理LIMIT子句的一处BUG所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(29)

评论列表共有 0 条评论

立即
投稿
返回
顶部