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

前端之家收集整理的这篇文章主要介绍了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的时候,谨慎!

bindParamPDOStatementPHP

猜你在找的PHP相关文章