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.NET的入门教程
Oct 09 PHP
加速XP搜索功能堪比vista
Mar 22 PHP
input file获得文件根目录简单实现
Apr 26 PHP
Codeigniter实现处理用户登录验证后的URL跳转
Jun 12 PHP
php单态设计模式(单例模式)实例
Nov 18 PHP
thinkphp循环结构用法实例
Nov 24 PHP
phplot生成图片类用法详解
Jan 06 PHP
php简单实现无限分类树形列表的方法
Mar 27 PHP
PHP生成指定随机字符串的简单实现方法
Apr 01 PHP
PHP getallheaders无法获取自定义头(headers)的问题
Mar 23 PHP
php数组分页实现方法
Apr 30 PHP
PHP通过调用新浪API生成t.cn格式短网址链接的方法详解
Feb 20 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
PHP导出EXCEL快速开发指南--PHPEXCEL的使用详解
2013/06/03 PHP
万能的php分页类
2017/07/06 PHP
JavaScript的9个陷阱及评点分析
2008/05/16 Javascript
Jquery插件之多图片异步上传
2010/10/20 Javascript
基于jquery完美拖拽,可返回拖动轨迹
2012/03/29 Javascript
JavaScript 作用域链解析
2014/11/13 Javascript
jQuery Ajax()方法使用指南
2014/11/19 Javascript
jQuery实现HTML5 placeholder效果实例
2014/12/09 Javascript
jQuery实现“扫码阅读”功能
2015/01/21 Javascript
javascript实现控制浏览器全屏
2015/03/30 Javascript
简介JavaScript中的getUTCFullYear()方法的使用
2015/06/10 Javascript
Bootstrap每天必学之滚动监听
2016/03/16 Javascript
jQuery AJAX timeout 超时问题详解
2016/06/21 Javascript
JS验证全角与半角及相互转化的介绍
2017/05/18 Javascript
详解vuex中mapState,mapGetters,mapMutations,mapActions的作用
2018/04/13 Javascript
基于vue中对鼠标划过事件的处理方式详解
2018/08/22 Javascript
Vue2.0点击切换类名改变样式的方法
2018/08/22 Javascript
vue 根据选择条件显示指定参数的例子
2019/11/09 Javascript
JS 事件机制完整示例分析
2020/01/15 Javascript
基于element-ui对话框el-dialog初始化的校验问题解决
2020/09/11 Javascript
Python中的rjust()方法使用详解
2015/05/19 Python
python logging 日志轮转文件不删除问题的解决方法
2016/08/02 Python
python使用for循环计算0-100的整数的和方法
2019/02/01 Python
django框架创建应用操作示例
2019/09/26 Python
python数据分析:关键字提取方式
2020/02/24 Python
python中os.remove()用法及注意事项
2021/01/31 Python
用CSS3来实现社交分享按钮
2014/11/11 HTML / CSS
SQL里面IN比较快还是EXISTS比较快
2012/07/19 面试题
学生自我鉴定范文
2013/10/04 职场文书
建筑文秘专业个人求职信范文
2013/12/28 职场文书
学习经验演讲稿
2014/05/10 职场文书
音乐节策划方案
2014/06/09 职场文书
绿色环保口号
2014/06/12 职场文书
领导班子四风问题个人对照检查材料
2014/10/04 职场文书
2015年事业单位工作总结
2015/04/27 职场文书
2016应届毕业生就业指导课心得体会
2016/01/15 职场文书