php pdo准备重复变量

时间:2011-09-29 22:04:00

标签: php pdo

在编写pdo语句时,是否可以重复变量的值?我的意思是:

$query = "UPDATE users SET firstname = :name WHERE firstname = :name";
$stmt = $dbh -> prepare($query);
$stmt -> execute(array(":name" => "Jackie"));

请注意,我重复“:name”名称,而我只提供一次值。我怎样才能做到这一点?

2 个答案:

答案 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);