×

phppdobindparam

phppdobindparam的简单介绍

admin admin 发表于2023-04-01 05:48:07 浏览46 评论0

抢沙发发表评论

本文目录一览:

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的时候,

谨慎!

php pdo中PDOStatement 类的bindParam和bindValue方法的区别

在PDOStatement 类中两种方法的具体说明如下

bool PDOStatement::bindParam ( mixed $parameter , mixed $variable [, int $data_type = PDO::PARAM_STR [, int $length [, mixed $driver_options ]]] )bool PDOStatement::bindValue ( mixed $parameter , mixed $value [, int $data_type = PDO::PARAM_STR ] )-phppdobindparam

区别1:bindParam是绑定一个参数到指定的变量名,bindValue则是把一个值绑定到一个参数

$db = new PDO('mysql:host=localhost;dbname=dbtest;charset=utf8','user','pass');$st = $db-prepare('select * from tabletest where id = ?');$id = 1;$st-bindParam(1,$id,PDO::PARAM_INT);//$st-bindValue(1,$id,PDO::PARAM_INT);-phppdobindparam

在上述代码中,不管是bindParam或者bindValue,都能够正常执行,但是如果换成如下代码$db = new PDO('mysql:host=localhost;dbname=dbtest;charset=utf8','user','pass');$st = $db-prepare('select * from tabletest where id = ?');$st-bindParam(1,1,PDO::PARAM_INT);//$st-bindValue(1,1,PDO::PARAM_INT);-phppdobindparam

bindParam就会报如下错误,但是bindValue却可以正常执行

Fatal error: Cannot pass parameter 2 by reference

总结:bindParam第二个参数有且只能是一个变量名, 不能是一个具体的值,bindValue既可以绑定一个变量名,又可以绑定一个值

区别2:不同于 PDOStatement::bindValue(),PDOStatement::bindParam()中的变量作为引用被绑定,并只在 PDOStatement::execute() 被调用的时候才取其值-phppdobindparam

$db = new PDO('mysql:host=localhost;dbname=dbtest;charset=utf8','user','pass');$st = $db-prepare('select * from tabletest where id = ?');$id = 1;$st-bindParam(1,$id,PDO::PARAM_INT);$id = 2;$st-execute();$rs = $st-fetchAll();print_r($rs);-phppdobindparam

首先给$id赋值为1,bindParam绑定变量,在execute前,更改$id为2,然后进行执行操作,此时获得的结果集是当id=2的时候的查询结果,并非是id为1时的查询结果,这就是变量作为引用的解释,在execute之前,我们可以对此变量进行替换,而执行execute操作时候代入的变量值,是该变量最后一次更改的值。$db = new PDO('mysql:host=localhost;dbname=dbtest;charset=utf8','user','pass');$st = $db-prepare('select * from tabletest where id = ?');$id = 1;$st-bindValue(1,$id,PDO::PARAM_INT);$id = 2;$st-execute();$rs = $st-fetchAll();print_r($rs);-phppdobindparam

而bindValue则不同,在使用bindValue绑定变量后,即使在执行execute之前改变了该变量的值,那么结果也不会变。例如上例中即使我们把$id改为了2,但是最后执行的结果仍然会输出$id

=1时候的结果,因为bindValue绑定的并非是变量的引用,不会随着变量的更改而更改。

虽然两者都能完成sql参数的绑定,但是两者仍然有区别,在实际应用中,我们应该选择适合我们的,下面举一个bindParam使用不当的例子

假设有一个数据表有整形id和字符串型name两个字段,有一数组数据$params = array(1,'张三')准备使用预处理进行插入,具体代码如下

$db = new PDO('mysql:host=localhost;dbname=dbtest;charset=utf8','user','pass');$st = $db-prepare('insert into tabletest(id,name) values(?,?)');$params = array(1,'张三');foreach($params as $k = $v){ $index = $k + 1; $st-bindParam($index,$v);}$st-execute();-phppdobindparam

正常情况被执行的sql语句应该是insert into tabletest(id,name) values(1,'张三');

其实真正执行的sql语句却是insert into tabletest(id,name) values('男','男');

究其原因就是bindParam中的变量作为了引用被绑定,因此最后每个字段插入的数值都变成了最后一个字段的值,而此时我们使用bindValue就不会出现这种问题了。此例中还有一点需要说明的是如果使用的是问号占位符和索引数组结合,特别需要注意bindValue的参数标识符(该方法的第一个参数),索引数组默认从0开始,而bindValue的参数标识符是以1开始,如果直接套入索引数组的0下标,那么程序就会报错,使用的时候一定需要注意。-phppdobindparam

php的PDO类中bindValue和bindParam的区别

1、bindParam是绑定一个参数到指定的变量名

bindValue则是把一个值绑定到一个参数

2、bindParam第二个参数有且只能是一个变量名, 不能是一个具体的值

bindValue既可以绑定一个变量名,又可以绑定一个值

3、不同于 PDOStatement::bindValue(),PDOStatement::bindParam()中的变量作为引用被绑定,并只在 PDOStatement::execute() 被调用的时候才取其值-phppdobindparam