問題描述
在編寫 pdo 語句時(shí),是否可以重復(fù)變量的值?我的意思是:
While writing a pdo statement, is it possible to repeat the value of a variable? I mean:
$query = "UPDATE users SET firstname = :name WHERE firstname = :name";
$stmt = $dbh -> prepare($query);
$stmt -> execute(array(":name" => "Jackie"));
請(qǐng)注意,我重復(fù)了 ":name" 名稱,而我只提供了一次該值.我怎樣才能做到這一點(diǎn)?
Please note that I repeat the ":name" nameholder whereas I provide the value only once. How can I make this work?
推薦答案
簡單的答案是:你不能.PDO 對(duì)準(zhǔn)備好的語句使用抽象,但有一些限制.不幸的是,這是一個(gè),您必須使用類似
The simple answer is: You can't. PDO uses an abstraction for prepared statements which has some limitations. Unfortunately this is one, you have to work-around using something like
$query = "UPDATE users SET firstname = :name1 WHERE firstname = :name2";
$stmt = $dbh -> prepare($query);
$stmt -> execute(array(":name1" => "Jackie", ":name2" => "Jackie"));
在某些情況下,例如使用某些版本的 PDO/MySQL 驅(qū)動(dòng)程序模擬準(zhǔn)備好的語句,支持重復(fù)命名參數(shù);但是,不應(yīng)依賴它,因?yàn)樗艽嗳?例如,它會(huì)使升級(jí)需要更多工作).
In certain cases, such as emulated prepared statements with some versions of the PDO/MySQL driver, repeated named parameters are supported; however, this shouldn't be relied upon, as it's brittle (it can make upgrades require more work, for example).
如果你想支持一個(gè)命名參數(shù)的多次出現(xiàn),你總是可以擴(kuò)展 PDO 和 PDOStatement(通過經(jīng)典繼承或通過組合),或者只是 PDOStatement 并通過設(shè)置 PDO::ATTR_STATEMENT_CLASS
屬性將您的類設(shè)置為語句類.擴(kuò)展的 PDOStatement(或 PDO::prepare
)可以提取命名參數(shù),查找重復(fù)并自動(dòng)生成替換.它還會(huì)記錄這些重復(fù)項(xiàng).bind 和 execute 方法在傳遞命名參數(shù)時(shí)會(huì)測試該參數(shù)是否重復(fù)并將值綁定到每個(gè)替換參數(shù).
If you want to support multiple appearances of a named parameter, you can always extend PDO and PDOStatement (by classical inheritance or by composition), or just PDOStatement and set your class as the statement class by setting the PDO::ATTR_STATEMENT_CLASS
attribute. The extended PDOStatement (or PDO::prepare
) could extract the named parameters, look for repeats and automatically generate replacements. It would also record these duplicates. The bind and execute methods, when passed a named parameter, would test whether the parameter is repeated and bind the value to each replacement parameter.
注意:以下示例未經(jīng)測試,可能存在錯(cuò)誤(一些與語句解析相關(guān)的在代碼注釋中注明).
Note: the following example is untested and likely has bugs (some related to statement parsing are noted in code comments).
class PDO_multiNamed extends PDO {
function prepare($stmt) {
$params = array_count_values($this->_extractNamedParams());
# get just named parameters that are repeated
$repeated = array_filter($params, function ($count) { return $count > 1; });
# start suffixes at 0
$suffixes = array_map(function ($x) {return 0;}, $repeated);
/* Replace repeated named parameters. Doesn't properly parse statement,
* so may replacement portions of the string that it shouldn't. Proper
* implementation left as an exercise for the reader.
*
* $param only contains identifier characters, so no need to escape it
*/
$stmt = preg_replace_callback(
'/(?:' . implode('|', array_keys($repeated)) . ')(?=W)/',
function ($matches) use (&$suffixes) {
return $matches[0] . '_' . $suffixes[$matches[0]]++;
}, $stmt);
$this->prepare($stmt,
array(
PDO::ATTR_STATEMENT_CLASS => array('PDOStatement_multiNamed', array($repeated)))
);
}
protected function _extractNamedParams() {
/* Not actually sufficient to parse named parameters, but it's a start.
* Proper implementation left as an exercise.
*/
preg_match_all('/:w+/', $stmt, $params);
return $params[0];
}
}
class PDOStatement_multiNamed extends PDOStatement {
protected $_namedRepeats;
function __construct($repeated) {
# PDOStatement::__construct doesn't like to be called.
//parent::__construct();
$this->_namedRepeats = $repeated;
}
/* 0 may not be an appropriate default for $length, but an examination of
* ext/pdo/pdo_stmt.c suggests it should work. Alternatively, leave off the
* last two arguments and rely on PHP's implicit variadic function feature.
*/
function bindParam($param, &$var, $data_type=PDO::PARAM_STR, $length=0, $driver_options=array()) {
return $this->_bind(__FUNCTION__, $param, func_get_args());
}
function bindValue($param, $var, $data_type=PDO::PARAM_STR) {
return $this->_bind(__FUNCTION__, $param, func_get_args());
}
function execute($input_parameters=NULL) {
if ($input_parameters) {
$params = array();
# could be replaced by array_map_concat, if it existed
foreach ($input_parameters as $name => $val) {
if (isset($this->_namedRepeats[$param])) {
for ($i=0; $i < $this->_namedRepeats[$param], ++$i) {
$params["{$name}_{$i}"] = $val;
}
} else {
$params[$name] = $val;
}
}
return parent::execute($params);
} else {
return parent::execute();
}
}
protected function _bind($method, $param, $args) {
if (isset($this->_namedRepeats[$param])) {
$result = TRUE;
for ($i=0; $i < $this->_namedRepeats[$param], ++$i) {
$args[0] = "{$param}_{$i}";
# should this return early if the call fails?
$result &= call_user_func_array("parent::$method", $args);
}
return $result;
} else {
return call_user_func_array("parent::$method", $args);
}
}
}
這篇關(guān)于php pdo 準(zhǔn)備重復(fù)變量的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!