PHP PDOStatement:bindParam插入数据错误问题分析


Posted in PHP onNovember 13, 2013

废话不多说, 直接看代码:

<?php
$dbh = new PDO('mysql:host=localhost;dbname=test', "test");$query = <<<QUERY
  INSERT INTO `user` (`username`, `password`) VALUES (:username, :password);
QUERY;
$statement = $dbh->prepare($query);
$bind_params = array(':username' => "laruence", ':password' => "weibo");
foreach( $bind_params as $key => $value ){
    $statement->bindParam($key, $value);
}
$statement->execute();

请问, 最终执行的SQL语句是什么, 上面的代码是否有什么问题?
Okey, 我想大部分同学会认为, 最终执行的SQL是:
INSERT INTO `user` (`username`, `password`) VALUES ("laruence", "weibo");
但是, 可惜的是, 你错了, 最终执行的SQL是:
INSERT INTO `user` (`username`, `password`) VALUES ("weibo", "weibo");
是不是很大的一个坑呢?
这个问题, 来自今天的一个Bug报告: #63281
究其原因, 也就是bindParam和bindValue的不同之处, bindParam要求第二个参数是一个引用变量(reference).
让我们把上面的代码的foreach拆开, 也就是这个foreach:
<?php
foreach( $bind_params as $key => $value ){
    $statement->bindParam($key, $value);
}

相当于:
<?php
//第一次循环
$value = $bind_params[":username"];
$statement->bindParam(":username", &$value); //此时, :username是对$value变量的引用//第二次循环
$value = $bind_params[":password"]; //oops! $value被覆盖成了:password的值
$statement->bindParam(":password", &$value);

所以, 在使用bindParam的时候, 尤其要注意和foreach联合使用的这个陷阱. 那么正确的作法呢?
1. 不要使用foreach, 而是手动赋值
<?php
$statement->bindParam(":username", $bind_params[":username"]); //$value是引用变量了
$statement->bindParam(":password", $bind_params[":password"]);

2. 使用bindValue代替bindParam, 或者直接在execute中传递整个参数数组.
3. 使用foreach和reference(不推荐)
<?php
foreach( $bind_params as $key => &$value ) { //注意这里
    $statement->bindParam($key, $value);
}

最后, 展开了说, 对于要求参数是引用, 并且有滞后处理的函数, 都要在使用foreach的时候, 谨慎!
PHP 相关文章推荐
如何使用PHP中的字符串函数
Oct 09 PHP
PHP获得用户使用的代理服务器ip即真实ip
Dec 31 PHP
PHP常用代码大全(新手入门必备)
Jun 29 PHP
PHP漏洞全解(详细介绍)
Nov 13 PHP
thinkphp文件引用与分支结构用法实例
Nov 26 PHP
PHP弹出对话框技巧详细解读
Sep 26 PHP
详解PHP的Yii框架中日志的相关配置及使用
Dec 08 PHP
简单谈谈php浮点数精确运算
Mar 10 PHP
PHP的swoole扩展安装方法详细教程
May 18 PHP
php中输出json对象的值(实现方法)
Mar 07 PHP
PHP给前端返回一个JSON对象的实例讲解
May 31 PHP
thinkPHP5.1框架中Request类四种调用方式示例
Aug 03 PHP
php curl模拟post请求小实例
Nov 13 #PHP
CodeIgniter生成网站sitemap地图的方法
Nov 13 #PHP
php模板原理讲解
Nov 13 #PHP
php构造函数实例讲解
Nov 13 #PHP
PHP将XML转数组过程详解
Nov 13 #PHP
PHP生成sitemap.xml地图函数
Nov 13 #PHP
使用PHP静态变量当缓存的方法
Nov 13 #PHP
You might like
isset和empty的区别
2007/01/15 PHP
利用PHP获取汉字首字母并且分组排序详解
2017/10/22 PHP
Gird事件机制初级读本
2007/03/10 Javascript
汉化英文版的Dreamweaver CS5并自动提示jquery
2010/11/25 Javascript
JQuery中$之选择器用法介绍
2011/04/05 Javascript
JavaScript中的isXX系列是否继续使用的分析
2011/04/16 Javascript
js获得指定控件输入光标的坐标兼容IE,Chrome,火狐等多种主流浏览器
2013/05/21 Javascript
javascript生成随机数的方法
2014/05/16 Javascript
javascript常见用法总结
2014/05/22 Javascript
node.js中的fs.openSync方法使用说明
2014/12/17 Javascript
jQuery双向列表选择器DIV模拟版
2016/11/01 Javascript
js实现消息滚动效果
2017/01/18 Javascript
js事件冒泡与事件捕获详解
2017/02/20 Javascript
微信小程序 轮播图实现原理及优化详解
2019/09/29 Javascript
jQuery操作元素的内容和样式完整实例分析
2020/01/10 jQuery
在vue中使用el-tab-pane v-show/v-if无效的解决
2020/08/03 Javascript
跟老齐学Python之编写类之三子类
2014/10/11 Python
python统计日志ip访问数的方法
2015/07/06 Python
详解Python的Django框架中的模版继承
2015/07/16 Python
Python实现监控键盘鼠标操作示例【基于pyHook与pythoncom模块】
2018/09/04 Python
python3 拼接字符串的7种方法
2018/09/12 Python
将Django项目部署到CentOs服务器中
2018/10/18 Python
Python查找文件中包含中文的行方法
2018/12/19 Python
使用Python Pandas处理亿级数据的方法
2019/06/24 Python
基于python实现蓝牙通信代码实例
2019/11/19 Python
python 上下文管理器及自定义原理解析
2019/11/19 Python
pytorch实现Tensor变量之间的转换
2020/02/17 Python
用什么库写 Python 命令行程序(示例代码详解)
2020/02/20 Python
使用Python发现隐藏的wifi
2020/03/04 Python
Django Serializer HiddenField隐藏字段实例
2020/03/31 Python
Python unittest基本使用方法代码实例
2020/06/29 Python
利用python查看数组中的所有元素是否相同
2021/01/08 Python
美特斯邦威官方商城:邦购网
2016/10/13 全球购物
自考生毕业自我鉴定
2013/10/10 职场文书
文明上网主题班会
2015/08/14 职场文书
人力资源部工作计划
2019/05/14 职场文书