PHP Conference Japan 2024

PDOStatement::bindValue

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

PDOStatement::bindValue 將值繫結至參數

說明

公開 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() 是以傳址 (byref) 方式傳遞給 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); // 作者 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()。
這是一個錯誤嗎?我不確定。
cpd-dev
14 年前
雖然 bindValue() 會跳脫引號,但它不會跳脫 "%" 和 "_",因此在使用 LIKE 時要小心。如果沒有自行跳脫參數,一個充滿 %%% 的惡意參數可能會傾印整個資料庫。PDO 沒有提供任何其他跳脫方法來處理它。
匿名
13 年前
請注意,在大多數情況下,第三個參數($data_type)並不會將值轉換成其他類型以供查詢使用,也不會在類型與提供的值不匹配時拋出任何錯誤。這個參數基本上沒有任何作用,除非設定了它且它不是浮點數時會拋出錯誤,所以不要認為它為查詢增加了任何額外的安全性。

執行類型轉換的兩個例外情況

- 如果您使用 PDO::PDO_PARAM_INT 並提供一個布林值,它將被轉換為長整數 (long)
- 如果您使用 PDO::PDO_PARAM_BOOL 並提供一個長整數 (long),它將被轉換為布林值

<?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 子句時特別有用,因為 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();
?>
輸出結果
注意:未定義的變數:val。

而在 bindParam 的情況下,值的評估要等到呼叫 execute() 時才會執行。這是為了利用傳參考的優點。
<?php
$st
= $db->prepare ("SELECT * FROM posts WHERE id = :val ");
$st->bindParam(':val',$val);

$val = '2';
//
// 一些程式碼
//
$val = '3'; // 重新賦值給變數
$st->execute();
?>
可以正常運作。
nicolas dot baptiste at gmail dot com
15 年前
這實際上可以在 MySQL 的整數欄位上綁定 NULL 值

$stm->bindValue(':param', null, PDO::PARAM_INT);
sageptr at gmail dot com
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 可能會導致查詢無聲無息地失敗並返回空集合。

在這種情況下,模擬預備語句的工作更穩定,因為它們會將所有內容轉換為字串,並決定是否要將參數加上引號。
goofiq dot no dot spam at antispam dot wp dot pl
14 年前
bindValue 的 data_type 取決於參數名稱

<?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