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的时候, 谨慎!
转自:http://www.laruence.com/2012/07/25/2662.html
PDOStatement::bindParam的一个陷阱的更多相关文章
- PDOStatement::bindParam
PDOStatement::bindParam — 绑定一个参数到指定的变量名(PHP 5 >= 5.1.0, PECL pdo >= 0.1.0) 说明 语法 bool PDOState ...
- 小知识:C#可选参数的一个陷阱
一.背景: 互联网行业,为了降低程序维护.升级的部署风险,往往会将程序拆分成很多项目,编译成多个dll部署,这样发布的时候,只需要部署修改过的dll即可. 二.问题: 有一个函数,在很多个地方被使 ...
- Vue的一个陷阱
最近做项目,上线前一直有个bug,不知道是什么原因引起的, vm.$set('needVerification', true); $('.verification-button').prop('dis ...
- python中from module import * 的一个陷阱
from module import *把module中的成员全部导到了当前的global namespace,访问起来就比较方便了.当然,python style一般不建议这么做,因为可能引起nam ...
- 用 managedQuery() 时须要注意的一个陷阱
Activity 里面提供了一个 managedQuery() 方法,依照 Android SDK 里面的说明,"the activity will manage its lifecycle ...
- Java的Comparable接口的一个陷阱
转载自:http://my.oschina.net/jack230230/blog/56339 Java的Comparable接口提供一个对实现了这个接口的对象列表进行排序的办法.原始的排序对于简单的 ...
- C语言补漏(1)--- char到int赋值的一个陷阱
作为一个C的新手(虽然学的第一门语言就是C,可是用C实际开发项目却是最近的事情),对使用C过程中遇到的各类问题.疑惑.知识漏洞进行弥补无疑是非常有必要的,于是决定将每次遇到的知识漏洞写到博客上. 今天 ...
- Delphi中返回类型为string的函数的一个陷阱(不是很懂)
如果类的一个成员函数的返回值是string类型,需要注意一个问题 其返回值可能是错误的 例如函数的实现如下 function GetString( s: string ): string;begin ...
- 调用scanf函数的一个陷阱
我们在写C程序时,经常使用scanf函数,让用户输入数据,可是有时候会出现一些很奇怪的问题.例如,下面的程序是一个简单的四则运算: #include <stdio.h> int main( ...
随机推荐
- Android画一条横线
<View android:layout_width="match_parent" android:layout_height="1px" android ...
- 使用 Fresco加载图片
概念: ImagePipeline ——负责从网络.本地图片.Content Provider(内容提供者)或者本地资源那里获取图片,压缩保存在本地存储中和在内存中保存为压缩的图片 Drawee——处 ...
- Sql server 日期函数和日期转换
时间函数 SQL Server Date 函数 下面的表格列出了 SQL Server 中最重要的内建日期函数: 函数 描述 GETDATE() 返回当前日期和时间 DATEPART(Type,dat ...
- codeforces723 D. Lakes in Berland(并查集)
题目链接:codeforces723 D. Lakes in Berland 参考博客:http://www.cnblogs.com/Geek-xiyang/p/5930245.html #inclu ...
- HDU 2546(01背包)
饭卡 Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submissi ...
- js数量添加(如购物车添加,删减数量)
<div class="fl shop-num ml24"><input type="button" style=" border- ...
- Spring的web应用启动加载数据字典方法
在一个基于Spring的web项目中,当我们需要在应用启动时加载数据字典时,可写一个监听实现javax.servlet.ServletContextListener 实现其中的contextIniti ...
- JBoss像tomcat那样创建部署文件,JBoss创建虚拟目录
jboss可以像tomcat那样,写一个配置文件,指向应用所在的路径,而不用将应用直接复制到deploy下的某一个以.war结尾的文件夹下吗? 答:好像是不能直接操作,但是可以通过变通的方式来搞定.在 ...
- ANGULARJS 动态编译添加到dom中
在使用angularjs 时,希望通过动态构建angular模版,再通过angular进行展示. 使用 方法如下: <html ng-app="app"> <he ...
- CF 241E flights 最短路,重复迭代直到稳定 难度:3
http://codeforces.com/problemset/problem/241/E 首先检测哪些点会出现在从起点到终点的路上,可以用dfs或者迭代, 然后,对于所有的边,设f为边起点,t为边 ...