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 相关文章推荐
多重?l件?合查?(二)
Oct 09 PHP
PHP simple_html_dom.php+正则 采集文章代码
Dec 24 PHP
php 各种应用乱码问题的解决方法
May 09 PHP
PHP中改变图片的尺寸大小的代码
Jul 17 PHP
数组与类使用PHP的可变变量名需要的注意的问题
Jun 20 PHP
thinkphp四种url访问方式详解
Nov 28 PHP
再谈PHP中单双引号的区别详解
Jun 12 PHP
mac下多个php版本快速切换的方法
Oct 09 PHP
PHP自动补全表单的两种方法
Mar 06 PHP
PHP智能识别收货地址信息实例
Jan 05 PHP
关于PHP求解三数之和问题详析
Nov 09 PHP
PHP执行系统命令函数实例讲解
Mar 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
2款PHP无限级分类实例代码
2015/11/11 PHP
TP5框架model常见操作示例小结【增删改查、聚合、时间戳、软删除等】
2020/04/05 PHP
用Javscript实现表单复选框的全选功能
2007/05/25 Javascript
向fckeditor编辑器插入指定代码的方法
2007/05/25 Javascript
YUI的Tab切换实现代码
2010/04/11 Javascript
jquery isType() 类型判断代码
2011/02/14 Javascript
jquery操作checked属性以及disabled属性的多种方法
2014/06/20 Javascript
javascript定时器完整实例
2015/02/10 Javascript
原生js实现手风琴功能(支持横纵向调用)
2017/01/13 Javascript
js调用刷新界面的几种方式
2017/05/03 Javascript
vue动态路由实现多级嵌套面包屑的思路与方法
2017/08/16 Javascript
JavaScript引用类型Date常见用法实例分析
2018/08/08 Javascript
微信小程序支付前端源码
2018/08/29 Javascript
解决vue同一slot在组件中渲染多次的问题
2018/09/06 Javascript
JavaScript数据结构之栈实例用法
2019/01/18 Javascript
[50:54]完美世界DOTA2联赛 GXR vs IO 第三场 11.07
2020/11/10 DOTA
Python黑魔法Descriptor描述符的实例解析
2016/06/02 Python
深入理解python中的atexit模块
2017/03/07 Python
Python中的pygal安装和绘制直方图代码分享
2017/12/08 Python
Python画柱状统计图操作示例【基于matplotlib库】
2018/07/04 Python
用python3 urllib破解有道翻译反爬虫机制详解
2019/08/14 Python
python每5分钟从kafka中提取数据的例子
2019/12/23 Python
Python安装依赖(包)模块方法详解
2020/02/14 Python
python从PDF中提取数据的示例
2020/10/30 Python
Python实现冒泡排序算法的完整实例
2020/11/04 Python
IE兼容css3圆角的实现代码
2011/07/21 HTML / CSS
如何强制垃圾回收
2015/10/06 面试题
人事主管岗位职责
2014/01/30 职场文书
计算机维护专业推荐信
2014/02/27 职场文书
倡议书格式模板
2014/05/13 职场文书
阅兵口号
2014/06/19 职场文书
员工辞职信怎么写
2015/02/27 职场文书
2015年民兵整组工作总结
2015/07/24 职场文书
《有余数的除法》教学反思
2016/02/22 职场文书
2019年自助餐厅创业计划书模板
2019/08/22 职场文书
python实现学员管理系统(面向对象版)
2022/06/05 Python