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 win下Socket方式发邮件类
Aug 21 PHP
PHP+SQL 注入攻击的技术实现以及预防办法
Dec 29 PHP
浅析PHP绘图技术
Jul 03 PHP
PHP mysql与mysqli事务使用说明 分享
Aug 17 PHP
PHP内核探索:变量概述
Jan 30 PHP
仿dedecms下拉分页样式修改的thinkphp分页类实例
Oct 30 PHP
Yii操作数据库实现动态获取表名的方法
Mar 29 PHP
php实现文件预览功能
May 23 PHP
PHP设计模式之工厂模式实例总结
Sep 01 PHP
Laravel学习教程之request validation的编写
Oct 25 PHP
在Ubuntu 18.04上安装PHP 7.3 7.2和7.0的方法
Apr 09 PHP
PHP 文件上传限制问题
Sep 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邮件类
2007/01/03 PHP
php内嵌函数用法实例
2015/03/20 PHP
PHP微信支付实例解析
2016/07/22 PHP
使用jquery实现IE下按backspace相当于返回操作
2014/03/18 Javascript
JavaScript实现把rgb颜色转换成16进制颜色的方法
2015/06/01 Javascript
JavaScritp添加url参数并将参数加入到url中及更改url参数的方法
2015/10/26 Javascript
DeviceOne 让你一见钟情的App快速开发平台
2016/02/17 Javascript
jQuery实现点击关注和取消功能
2017/07/03 jQuery
JS实现按钮添加背景音乐示例代码
2017/10/17 Javascript
js实现图片放大并跟随鼠标移动特效
2019/01/18 Javascript
tweenjs缓动算法的使用实例分析
2019/08/26 Javascript
JsonProperty 的使用方法详解
2019/10/11 Javascript
微信小程序自定义菜单切换栏tabbar组件代码实例
2019/12/30 Javascript
Python递归遍历列表及输出的实现方法
2015/05/19 Python
python ipset管理 增删白名单的方法
2019/01/14 Python
Django高级编程之自定义Field实现多语言
2019/07/02 Python
Python调用.NET库的方法步骤
2019/12/27 Python
在python里使用await关键字来等另外一个协程的实例
2020/05/04 Python
python模拟点击玩游戏的实例讲解
2020/11/26 Python
全球虚拟主机商:HostGator
2017/02/06 全球购物
日本7net购物网:书籍、漫画、杂志、DVD、游戏邮购
2017/02/17 全球购物
西海岸男士和男童服装:Johnnie-O
2018/03/15 全球购物
俄罗斯运动、健康和美容产品在线商店:Lactomin.ru
2020/07/23 全球购物
巴西购物网站:Onofre Agora
2020/06/08 全球购物
超市营业员求职简历的自我评价
2013/10/17 职场文书
医务人员竞聘职务自我评价分享
2013/11/08 职场文书
生日派对邀请函
2014/01/13 职场文书
建筑系毕业生自我鉴定
2014/01/24 职场文书
幼儿教师国培感言
2014/02/19 职场文书
继承公证书样本
2014/04/04 职场文书
西游降魔篇观后感
2015/06/15 职场文书
钢铁是怎样炼成的读书笔记
2015/06/29 职场文书
基层党建工作简报
2015/07/21 职场文书
认识实习感想
2015/08/10 职场文书
一篇文章弄懂Python关键字、标识符和变量
2021/07/15 Python
opencv深入浅出了解机器学习和深度学习
2022/03/17 Python