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 相关文章推荐
fleaphp crud操作之find函数的使用方法
Apr 23 PHP
PHP中最容易忘记的一些知识点总结
Apr 28 PHP
php的sso单点登录实现方法
Jan 08 PHP
以文件形式缓存php变量的方法
Jun 26 PHP
PHP strip_tags保留多个HTML标签的方法
May 22 PHP
Laravel中使用FormRequest进行表单验证方法及问题汇总
Jun 19 PHP
PHP中new static()与new self()的比较
Aug 19 PHP
完美的php分页类
Oct 24 PHP
PHP实现求连续子数组最大和问题2种解决方法
Dec 26 PHP
PHP命名空间与自动加载机制的基础介绍
Aug 25 PHP
Laravel框架实现抢红包功能示例
Oct 31 PHP
PHP+Mysql分布式事务与解决方案深入理解
Feb 27 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中addslashes与mysql_escape_string的区别分析
2016/04/25 PHP
PHP正则匹配日期和时间(时间戳转换)的实例代码
2016/12/14 PHP
用javascript为页面添加天气显示实现思路及代码
2013/12/02 Javascript
JS中产生标识符方式的演变
2015/06/12 Javascript
JavaScript图片轮播代码分享
2015/07/31 Javascript
JS模仿手机端九宫格登录功能实现代码
2016/04/28 Javascript
jQuery基础的工厂函数以及定时器的经典实例分析
2016/05/20 Javascript
JS对HTML表格进行增删改操作
2016/08/22 Javascript
JS实现仿饿了么在浏览器标签页失去焦点时网页Title改变
2017/06/01 Javascript
JS倒计时实例_天时分秒
2017/08/22 Javascript
javascript按顺序加载运行js方法
2017/12/01 Javascript
浅谈ajax请求不同页面的微信JSSDK问题
2018/02/26 Javascript
Django+Vue跨域环境配置详解
2018/07/06 Javascript
微信小程序实现图片滚动效果示例
2018/12/05 Javascript
js中arguments对象的深入理解
2019/05/14 Javascript
Vue程序调试的方法
2019/06/17 Javascript
JS获取当前时间的年月日时分秒及时间的格式化的方法
2019/12/18 Javascript
python计算对角线有理函数插值的方法
2015/05/07 Python
python微信跳一跳系列之自动计算跳一跳距离
2018/02/26 Python
如何利用python查找电脑文件
2018/04/27 Python
Python实现将数据写入netCDF4中的方法示例
2018/08/30 Python
django创建最简单HTML页面跳转方法
2019/08/16 Python
Python Pivot table透视表使用方法解析
2020/09/11 Python
英国内衣连锁店:Boux Avenue
2018/01/24 全球购物
几道数据库的面试题或笔试题
2014/05/31 面试题
创联软件面试题笔试题
2012/10/07 面试题
省优秀教师事迹材料
2014/01/30 职场文书
聊城大学毕业生自荐书
2014/02/01 职场文书
公务员四风问题对照检查材料整改措施
2014/09/26 职场文书
村党支部书记四风问题个人对照检查材料思想汇报
2014/10/06 职场文书
大学感恩节活动策划方案
2014/10/11 职场文书
大学生逃课检讨书
2015/05/04 职场文书
导游词之京东大峡谷旅游区
2019/10/29 职场文书
聊聊redis-dump工具安装问题
2022/01/18 Redis
动漫APP软件排行榜前十名,半次元上榜,第一款由腾讯公司推出
2022/03/18 杂记
golang生成vcf通讯录格式文件详情
2022/03/25 Golang