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 无限级 SelectTree 类
May 19 PHP
几款免费开源的不用数据库的php的cms
Dec 19 PHP
PHP中simplexml_load_string函数使用说明
Jan 01 PHP
PHP操作数组的一些函数整理介绍
Jul 17 PHP
php中设置index.php文件为只读的方法
Feb 06 PHP
php 无法加载mcrypt.dll的解决办法
Apr 03 PHP
CI框架Session.php源码分析
Nov 03 PHP
php实现的简单美国商品税计算函数
Jul 13 PHP
使用PHP编写发红包程序
Jul 22 PHP
必须收藏的23个php实用代码片段
Feb 02 PHP
PHP实现的获取文件mimes类型工具类示例
Apr 08 PHP
Jsonp劫持学习
Apr 01 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 VS ASP
2006/10/09 PHP
php实现excel中rank函数功能的方法
2015/01/20 PHP
php中 $$str 中 &quot;$$&quot; 的详解
2015/07/06 PHP
PHP不使用递归的无限级分类简单实例
2016/11/05 PHP
ajax+php实现无刷新验证手机号的实例
2017/12/22 PHP
PHP类的自动加载机制实现方法分析
2019/01/10 PHP
laravel7学习之无限级分类的最新实现方法
2020/09/30 PHP
JQuery的ajax基础上的超强GridView展示
2009/09/18 Javascript
jQuery each()方法的使用方法
2010/03/18 Javascript
jquery连缀语法如何实现
2012/11/29 Javascript
js关于精确计算和数值格式化以及直接引js文件
2014/01/28 Javascript
JavaScript实现打开链接页面的方式汇总
2016/06/02 Javascript
JavaScript实战之菜单特效
2016/08/16 Javascript
vue中渐进过渡效果实现
2016/10/27 Javascript
使用vue.js编写蓝色拼图小游戏
2017/03/17 Javascript
JavaScript定时器setTimeout()和setInterval()详解
2017/08/18 Javascript
基于three.js编写的一个项目类示例代码
2018/01/05 Javascript
JS hasOwnProperty()方法检测一个属性是否是对象的自有属性的方法
2021/01/29 Javascript
[03:31]DOTA2英雄基础教程 大地之灵
2013/12/17 DOTA
[49:21]完美世界DOTA2联赛循环赛 Ink Ice vs LBZS BO2第二场 11.05
2020/11/06 DOTA
Python continue语句用法实例
2014/03/11 Python
TensorFlow实现Logistic回归
2018/09/07 Python
python中的反斜杠问题深入讲解
2019/08/12 Python
python 和c++实现旋转矩阵到欧拉角的变换方式
2019/12/04 Python
基于pytorch padding=SAME的解决方式
2020/02/18 Python
python中使用you-get库批量在线下载bilibili视频的教程
2020/03/10 Python
css3简单练习实现遨游浏览器logo的绘制
2013/01/30 HTML / CSS
Urban Decay官方网站:美国化妆品品牌
2020/06/04 全球购物
生产车间主任的个人自我鉴定
2013/10/25 职场文书
早会主持词
2014/03/17 职场文书
2014年环保工作总结
2014/11/26 职场文书
超级礼物观后感
2015/06/15 职场文书
赤壁观后感(2)
2015/06/15 职场文书
Python标准库之typing的用法(类型标注)
2021/06/02 Python
go语言中http超时引发的事故解决
2021/06/02 Golang
Mysql排查分析慢sql之explain实战案例
2022/04/19 MySQL