加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

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

发布时间:2020-12-12 19:58:26 所属栏目:PHP教程 来源:网络整理
导读:废话不多说,直接看代码: 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;dbn

废话不多说,直接看代码:
<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的时候,谨慎!

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读