在编写pdo语句时,是否可以重复变量的值?我的意思是:
$query = "UPDATE users SET firstname = :name WHERE firstname = :name";
$stmt = $dbh -> prepare($query);
$stmt -> execute(array(":name" => "Jackie"));
请注意,我重复“:name”名称,而我只提供一次值。我怎样才能做到这一点?
答案 0 :(得分:21)
简单的答案是:你做不到。 PDO对预准备语句使用抽象,这有一些限制。不幸的是,这是一个,你必须使用像
这样的东西来解决$query = "UPDATE users SET firstname = :name1 WHERE firstname = :name2";
$stmt = $dbh -> prepare($query);
$stmt -> execute(array(":name1" => "Jackie", ":name2" => "Jackie"));
在某些情况下,例如使用某些版本的PDO / MySQL驱动程序模拟预准备语句,支持重复的命名参数;但是,这不应该依赖,因为它很脆弱(例如,它可以使升级需要更多的工作)。
如果要支持命名参数的多个外观,可以始终extend PDO and PDOStatement(通过经典继承或组合),或者只是PDOStatement,并通过设置{{1}将您的类设置为语句类}属性。扩展的PDOStatement(或PDO::ATTR_STATEMENT_CLASS
)可以提取命名参数,查找重复并自动生成替换。它还会记录这些重复项。当传递一个命名参数时,bind和execute方法将测试参数是否重复并将值绑定到每个替换参数。
注意:以下示例未经测试,可能存在错误(在代码注释中记录了与语句解析相关的一些错误。)
PDO::prepare
答案 1 :(得分:0)
在我的情况下,当我从dblib freedts切换到sqlsrv PDO驱动程序时出现此错误。 Dblib驱动程序处理了重复的参数名称而没有错误。我有很多复杂的动态查询,有很多联合和很多重复的参数,所以我使用了以下帮助器作为解决方法:
function prepareMsSqlQueryParams($query, $params): array
{
$paramsCount = [];
$newParams = [];
$pattern = '/(:' . implode('|:', array_keys($params)) . ')/';
$query = preg_replace_callback($pattern, function ($matches) use ($params, &$newParams, &$paramsCount) {
$key = ltrim($matches[0], ':');
if (isset($paramsCount[$key])) {
$paramsCount[$key]++;
$newParams[$key . $paramsCount[$key]] = $params[$key];
return $matches[0] . $paramsCount[$key];
} else {
$newParams[$key] = $params[$key];
$paramsCount[$key] = 0;
return $matches[0];
}
}, $query);
return [$query, $newParams];
}
然后你可以这样使用它:
$query = "UPDATE users SET firstname = :name WHERE firstname = :name";
$params = [":name" => "Jackie"];
// It will return "UPDATE users SET firstname = :name WHERE firstname = :name1"; with appropriate parameters array
list($query, $params) = prepareMsSqlQueryParams($query, $params);
$stmt = $dbh->prepare($query);
$stmt->execute(params);