PHP PDOStatement:bindParam插入数据错误问题分析

2015-01-24信息快讯网

PHP PDOStatement:bindParam插入数据错误问题分析,开发中一定要注意

废话不多说, 直接看代码:
<?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的时候, 谨慎!
ThinkPHP3.1基础知识快速入门
php使用百度ping服务代码实例
ThinkPHP模板引擎之导入资源文件方法详解
ThinkPHP CURD方法之field方法详解
ThinkPHP CURD方法之data方法详解
ThinkPHP CURD方法之page方法详解
Smarty局部缓存的几种方法简介
smarty模板局部缓存方法使用示例
PHPAnalysis中文分词类详解
php smarty truncate UTF8乱码问题解决办法
PHP错误Cannot use object of type stdClass as array in错误的解决办法
PHP微框架Dispatch简介
PHP开源开发框架ZendFramework使用中常见问题说明及解决方案
PHP命名空间(Namespace)简明教程
CI框架中libraries,helpers,hooks文件夹详细说明
PHP、Nginx、Apache中禁止网页被iframe引用的方法
php+js iframe实现上传头像界面无跳转
php环境套包 dedeampz 伪静态设置示例
使用php验证复选框有效性的示例
php curl模拟post请求小实例
session在php5.3中的变化 session_is_registered() is deprecated in
php inc文件使用的风险和注意事项
PHP中ob_start函数的使用说明
PHP imagegrabscreen和imagegrabwindow(截取网站缩略图)的实例代码
php使用mb_check_encoding检查字符串在指定的编码里是否有效
php生成图形(Libchart)实例
php ZipArchive压缩函数详解实例
php define的第二个参数使用方法
在PHP上显示JFreechart画的统计图方法
php session_start()出错原因分析及解决方法
php中OR与|| AND与&&的区别总结
zend optimizer在wamp的基础上安装图文教程
PHP关于IE下的iframe跨域导致session丢失问题解决方法
php MessagePack介绍
php中利用str_pad函数生成数字递增形式的产品编号
php stream_get_meta_data返回值
DOM XPATH获取img src值的query
PHP引用符&的用法详细解析
浅析linux下apache服务器的配置和管理
©2014-2024 dbsqp.com