简单的答案是:您不能。PDO对准备好的语句使用了抽象,这有一定的局限性。不幸的是,这是一个问题,您必须使用类似的方法来解决
$query = "UPDATE users SET firstname = :name1 WHERe firstname = :name2";$stmt = $dbh -> prepare($query);$stmt -> execute(array(":name1" => "Jackie", ":name2" => "Jackie"));在某些情况下,例如使用某些版本的PDO /
MySQL驱动程序模拟准备好的语句,则支持重复的命名参数;但是,这不应该依赖,因为它很脆弱(例如,升级可能需要更多的工作)。
如果要支持命名参数的多个外观,则始终可以扩展PDO和PDOStatement(通过经典继承或按组成),也可以仅扩展PDOStatement,然后通过设置
PDO::ATTR_STATEMENT_CLASS属性将类设置为语句类。扩展的PDOStatement(或
PDO::prepare)可以提取命名的参数,查找重复项并自动生成替换项。它还将记录这些重复项。当绑定和执行方法传递一个命名参数时,它将测试该参数是否重复并将该值绑定到每个替换参数。
注意:以下示例未经测试,并且可能存在错误(一些与语句解析有关的错误在代码注释中注明)。
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); $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() { 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; } 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); } }}


