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+mysql)
Nov 23 PHP
PHP 高级课程笔记 面向对象
Jun 21 PHP
php入门学习知识点三 PHP上传
Jul 14 PHP
初品cakephp 入门基础
Feb 16 PHP
PHP curl使用实例
Jul 02 PHP
PHP获取表单数据与HTML嵌入PHP脚本的实现
Feb 09 PHP
php使用PDO事务配合表格读取大量数据插入操作实现方法
Feb 16 PHP
PHP快速推送微信模板消息
Apr 14 PHP
thinkPHP5.0框架验证码调用及点击图片刷新简单实现方法
Sep 07 PHP
php tpl模板引擎定义与使用示例
Aug 09 PHP
PHP获取类私有属性的3种方法
Sep 10 PHP
laravel7学习之无限级分类的最新实现方法
Sep 30 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 多个submit提交表单 处理方法
2009/07/07 PHP
php运行出现Call to undefined function curl_init()的解决方法
2010/11/02 PHP
PHP实现基于mysqli的Model基类完整实例
2016/04/08 PHP
Nigma vs Alliance BO5 第四场2.14
2021/03/10 DOTA
Code:findPosX 和 findPosY
2006/12/20 Javascript
JQuery UI皮肤定制
2009/07/27 Javascript
JQuery优缺点分析说明
2011/04/10 Javascript
node.js chat程序如何实现Ajax long-polling长链接刷新模式
2012/03/13 Javascript
CodeMirror2 IE7/IE8 下面未知运行时错误的解决方法
2012/03/29 Javascript
textarea 控制输入字符字节数(示例代码)
2013/12/27 Javascript
javascript获取form里的表单元素的示例代码
2014/02/14 Javascript
使用jquery写个更改表格行顺序的小功能
2014/04/29 Javascript
jQuery简易图片放大特效示例代码
2014/06/09 Javascript
Internet Explorer 11 浏览器介绍:别叫我IE
2014/09/28 Javascript
JS+CSS实现DIV层的展开、收缩效果
2016/01/28 Javascript
url中的特殊符号有什么含义(推荐)
2016/06/17 Javascript
JavaScript从0开始构思表情插件
2016/07/26 Javascript
jQuery UI制作选项卡(tabs)
2016/12/13 Javascript
jQuery编写设置和获取颜色的插件
2017/01/09 Javascript
React组件的三种写法总结
2017/01/12 Javascript
微信小程序websocket实现即时聊天功能
2019/05/21 Javascript
Element-UI 使用el-row 分栏布局的教程
2020/10/26 Javascript
Python学习笔记之常用函数及说明
2014/05/23 Python
Python内存读写操作示例
2018/07/18 Python
浅谈Python反射 &amp; 单例模式
2019/03/21 Python
浅谈Python大神都是这样处理XML文件的
2019/05/31 Python
在PyCharm中控制台输出日志分层级分颜色显示的方法
2019/07/11 Python
tensorflow实现读取模型中保存的值 tf.train.NewCheckpointReader
2020/02/10 Python
CSS3 实现飘动的云朵动画
2020/12/01 HTML / CSS
债务纠纷委托书范本
2014/10/14 职场文书
2015年专项整治工作总结
2015/04/03 职场文书
2015年保险公司工作总结
2015/04/24 职场文书
2015年幼儿园中班开学寄语
2015/05/27 职场文书
pytorch 预训练模型读取修改相关参数的填坑问题
2021/06/05 Python
Python torch.flatten()函数案例详解
2021/08/30 Python
SQL Server中使用表变量和临时表
2022/05/20 SQL Server