2024 PHP 日本大会

PDOStatement::bindValue

(PHP 5 >= 5.1.0, PHP 7, PHP 8, PECL pdo >= 1.0.0)

PDOStatement::bindValue绑定值到参数

描述

public PDOStatement::bindValue(字符串|整数 $param, 混合 $value, 整数 $type = PDO::PARAM_STR): 布尔值

将值绑定到用于准备语句的 SQL 语句中相应的命名或问号占位符。

参数

param

参数标识符。对于使用命名占位符的预处理语句,这将是 :name 形式的参数名称。对于使用问号占位符的预处理语句,这将是参数的 1 索引位置。

value

要绑定到参数的值。

type

使用 PDO::PARAM_* 常量 的参数的显式数据类型。

返回值

成功时返回 true,失败时返回 false

错误/异常

如果属性 PDO::ATTR_ERRMODE 设置为 PDO::ERRMODE_WARNING,则发出级别为 E_WARNING 的错误。

如果属性 PDO::ATTR_ERRMODE 设置为 PDO::ERRMODE_EXCEPTION,则抛出 PDOException

示例

示例 #1 使用命名占位符执行预处理语句

<?php
/* 通过绑定 PHP 变量来执行预处理语句 */
$calories = 150;
$colour = 'red';
$sth = $dbh->prepare('SELECT name, colour, calories
FROM fruit
WHERE calories < :calories AND colour = :colour'
);

/* 使用名称设置参数值 */
$sth->bindValue('calories', $calories, PDO::PARAM_INT);
/* 可选地,参数名称也可以用冒号 ":" 为前缀 */
$sth->bindValue(':colour', $colour, PDO::PARAM_STR);
$sth->execute();
?>

示例 #2 使用问号占位符执行预处理语句

<?php
/* 通过绑定 PHP 变量来执行预处理语句 */
$calories = 150;
$colour = 'red';
$sth = $dbh->prepare('SELECT name, colour, calories
FROM fruit
WHERE calories < ? AND colour = ?'
);
$sth->bindValue(1, $calories, PDO::PARAM_INT);
$sth->bindValue(2, $colour, PDO::PARAM_STR);
$sth->execute();
?>

参见

添加注释

用户贡献注释 11 条注释

streaky at mybrokenlogic dot com
16 年前
bindValue() 文档没有解释清楚的地方(除非非常仔细地阅读)是 bindParam() 是通过引用传递给 PDO 的——而 bindValue() 不是。

因此,使用 bindValue(),您可以执行类似 $stmt->bindValue(":something", "bind this"); 的操作,而使用 bindParam() 将失败,因为例如您不能通过引用传递字符串。
D.Kellner
8 年前
绑定参数时,显然你不能重复使用占位符(例如,“select * from mails where sender=:me or recipient=:me”),你必须给他们不同的名字,否则你的查询将返回空结果(但不会失败,不幸的是)。如果你正在努力解决类似的问题,请注意这一点。
e-ruiz at git hub
8 年前
尝试使用 PDO::PARAM_INT 进行验证时要小心。

请考虑这个示例

<?php
/* php --version
* PHP 5.6.25 (cli) (built: Aug 24 2016 09:50:46)
* Copyright (c) 1997-2016 The PHP Group
* Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
*/

$id = '1a';
$stm = $pdo->prepare('select * from author where id = :id');
$bind = $stm->bindValue(':id', $id, PDO::PARAM_INT);

$stm->execute();
$authors = $stm->fetchAll();

var_dump($id); // string(2)
var_dump($bind); // true
var_dump((int)$id); // int(1)
var_dump(is_int($id)); // false
var_dump($authors); // the author id=1 =(

// 请记住
var_dump(1 == '1'); // true
var_dump(1 === '1'); // false
var_dump(1 === '1a'); // false
var_dump(1 == '1a'); // true
?>

我的观点:bindValue() 应该首先内部测试 is_int()。
这是个bug吗?我不确定。
cpd-dev
14年前
虽然 bindValue() 转义了引号,但它没有转义 "%" 和 "_",因此在使用 LIKE 时要小心。如果自己不转义参数,则充满 %%% 的恶意参数可能会转储整个数据库。PDO 没有提供任何其他转义方法来处理它。
匿名用户
13年前
请注意,在大多数情况下,第三个参数 ($data_type) 不会将值类型转换为其他任何内容以用于查询,如果类型与提供的值不匹配,它也不会引发任何错误。此参数实际上没有任何效果,除非它已设置且不是浮点数时会引发错误,因此不要认为它为查询增加了任何额外的安全级别。

执行类型转换的两个例外情况:

- 如果你使用 PDO::PDO_PARAM_INT 并提供一个布尔值,它将被转换为长整型。
- 如果你使用 PDO::PDO_PARAM_BOOL 并提供一个长整型,它将被转换为布尔值。

<?php

$query
= 'SELECT * FROM `users` WHERE username = :username AND `password` = ENCRYPT( :password, `crypt_password`)';

$sth= $dbh->prepare($query);

// 首先尝试将随机数值作为第三个参数传递
var_dump($sth->bindValue(':username','bob', 12345.67)); // bool(true)

// 接下来尝试使用布尔类型传递字符串
var_dump($sth->bindValue(':password','topsecret_pw', PDO::PARAM_BOOL)); // bool(true)

$sth->execute(); // 查询成功执行
$result = $sth->fetchAll(); // 返回查询结果

?>
contact[at]maximeelomari.com
13年前
此函数可用于对数组进行值绑定。您可以使用 $typeArray 预先指定值的类型。

<?php
/**
* @param string $req : 要绑定值的查询
* @param array $array : 包含要绑定的值的关联数组
* @param array $typeArray : 关联数组,其中包含其在 $array 中的相应键的所需值
* */
function bindArrayValue($req, $array, $typeArray = false)
{
if(
is_object($req) && ($req instanceof PDOStatement))
{
foreach(
$array as $key => $value)
{
if(
$typeArray)
$req->bindValue(":$key",$value,$typeArray[$key]);
else
{
if(
is_int($value))
$param = PDO::PARAM_INT;
elseif(
is_bool($value))
$param = PDO::PARAM_BOOL;
elseif(
is_null($value))
$param = PDO::PARAM_NULL;
elseif(
is_string($value))
$param = PDO::PARAM_STR;
else
$param = FALSE;

if(
$param)
$req->bindValue(":$key",$value,$param);
}
}
}
}

/**
* ## 示例 ##
* $array = array('language' => 'php','lines' => 254, 'publish' => true);
* $typeArray = array('language' => PDO::PARAM_STR,'lines' => PDO::PARAM_INT,'publish' => PDO::PARAM_BOOL);
* $req = 'SELECT * FROM code WHERE language = :language AND lines = :lines AND publish = :publish';
* 你可以这样绑定 $array:
* bindArrayValue($array,$req,$typeArray);
* 当你使用 limit 子句时,此函数更有用,因为它们需要整数。
* */
?>
Vladimir Kovpak
9年前
<?php
/**
* 绑定位值。
*/

$sql = 'SELECT * FROM myTable WHERE level & ?';
$sth = \App::pdo()->prepare($sql);
$sth->bindValue(1, 0b0101, \PDO::PARAM_INT);
$sth->execute();
$result = $sth->fetchAll(\PDO::FETCH_ASSOC);
me at iabdullah dot info
10年前
我们无法在调用 bindValue() 后定义值变量的原因是,它会立即将值绑定到预处理语句,并且不会等到 execute() 发生。

以下代码将发出通知并阻止查询执行
<?php
$st
= $db->prepare ("SELECT * FROM posts WHERE id= :val ");
$st->bindValue(':val',$val);

$val = '2';
$st->execute();
?>
输出
Notice: Undefined variable: val.

而在 bindParam 的情况下,直到调用 execute() 才会执行对参数的值求值。这是为了获得引用传递的益处。
<?php
$st
= $db->prepare ("SELECT * FROM posts WHERE id = :val ");
$st->bindParam(':val',$val);

$val = '2';
//
// 一些代码
//
$val = '3'; // 重新赋值变量
$st->execute();
?>
运行正常。
[email protected]
15年前
这实际上可以在MySQL的整数字段中绑定NULL

$stm->bindValue(':param', null, PDO::PARAM_INT);
[email protected]
8 年前
注意极端情况!
使用MySQL原生预处理,你的整数在某些机器上可能会发生溢出

<?php
$x
= 2147483648;
var_dump($x); // 输出:int(2147483648)
$s = $db->prepare('SELECT :int AS I, :str AS S;');
$s->bindValue(':int', $x, PDO::PARAM_INT);
$s->bindValue(':str', $x, PDO::PARAM_STR);
$s->execute();
var_dump( $s->fetchAll(PDO::FETCH_ASSOC) );
/* 输出:array(2) {
["I"]=>
string(11) "-2147483648"
["S"]=>
string(10) "2147483648"
} */
?>

此外,尝试使用MySQL原生预处理绑定PDO::PARAM_BOOL可能会导致查询静默失败并返回空集。

模拟预处理在这种情况下工作更稳定,因为它们将所有内容转换为字符串,并只决定是否需要引用参数。
[email protected]
14年前
bindValue 的数据类型取决于参数名称

<?php

$db
= new PDO (...);
$db -> setAttribute (PDO::ATTR_STATEMENT_CLASS, array ('MY_PDOStatement ', array ($db)));

class
MY_PDOStatement extends PDOStatement {

public function
execute ($input = array ()) {
foreach (
$input as $param => $value) {
if (
preg_match ('/_id$/', $param))
$this -> bindValue ($param, $value, PDO::PARAM_INT);
else
$this -> bindValue ($param, $value, PDO::PARAM_STR);
}
return
parent::execute ();
}

}

?>
To Top