微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

废话不多说,直接看代码:
<div class="codetitle"><a style="CURSOR: pointer" data="99033" class="copybut" id="copybut99033" onclick="doCopy('code99033')"> 代码如下:

<div class="codebody" id="code99033">
<?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");
但是,可惜的是,你错了,password) VALUES ("weibo","weibo");
是不是很大的一个坑呢?
这个问题,来自今天的一个Bug报告: #63281
究其原因,也就是bindParam和bindValue的不同之处,bindParam要求第二个参数是一个引用变量(reference).
让我们把上面的代码的foreach拆开,也就是这个foreach:
<div class="codetitle"><a style="CURSOR: pointer" data="90747" class="copybut" id="copybut90747" onclick="doCopy('code90747')"> 代码如下:
<div class="codebody" id="code90747">
<?PHP
foreach( $bind_params as $key => $value ){
$statement->bindParam($key,$value);
}

相当于:
<div class="codetitle"><a style="CURSOR: pointer" data="68721" class="copybut" id="copybut68721" onclick="doCopy('code68721')"> 代码如下:
<div class="codebody" id="code68721">
<?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,而是手动赋值
<div class="codetitle"><a style="CURSOR: pointer" data="8242" class="copybut" id="copybut8242" onclick="doCopy('code8242')"> 代码如下:
<div class="codebody" id="code8242">
<?PHP
$statement->bindParam(":username",$bind_params[":username"]); //$value是引用变量了
$statement->bindParam(":password",$bind_params[":password"]);

2. 使用bindValue代替bindParam,或者直接在execute中传递整个参数数组.
3. 使用foreach和reference(不推荐)
<div class="codetitle"><a style="CURSOR: pointer" data="89679" class="copybut" id="copybut89679" onclick="doCopy('code89679')"> 代码如下:<div class="codebody" id="code89679">
<?PHP
foreach( $bind_params as $key => &$value ) { //注意这里
$statement->bindParam($key,$value);
}

最后,展开了说,对于要求参数是引用,并且有滞后处理的函数,都要在使用foreach的时候,谨慎!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

bindParamPDOStatementPHP

相关推荐