当前位置: 首页 > 面试题库 >

PHP PDO准备重复变量

司空叶五
2023-03-14
问题内容

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

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

请注意,我重复“:name”名称持有者,而我只提供一次值。我该如何进行这项工作?


问题答案:

简单的答案是:您不能。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);
        /* 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);
        }
    }
}


 类似资料:
  • 我用语句编写了这段代码,它运行良好: 但当我试图用PreparedStatement转换它时,它却不能处理SQL语法错误。

  • 我使用java PreparedStatment对象来构造一系列批处理的插入查询。查询语句的格式为。。。 ...所以字段值和表名都是变量(即。我有多个具有相同列格式的表,每个插入都将定向到不同的表)。如果我删除“?”tablename变量和硬代码,我可以让执行程序正常工作,但每个准备好的语句都将插入到不同的表中,因此需要保留一个我在使用...执行批处理查询之前立即填充的变量... 我怎样才能让它成

  • 我正在使用编写我认为是相当基本的准备好的状态。语句如下所示(其中是实例): 这将失败,在中的参数数不匹配。

  • 首先,我知道这是一个重复的问题,我问的是同样的问题。但是我已经阅读了所有与相同问题相关联的解决方案,但是当我遵循建议的解决方案时,它将触发更多的警告出现。这就是我的代码 获取 只为得到这些警告; 警告:mysqli_stmt::bind_param():第119行C:\xampp\htdocs\gsd\emergency\records.php中的变量数与准备好的语句中的参数数不匹配 警告:mys

  • 我正在尝试运行两个stmt并将它们与php绑定。当我刚刚运行$stmt并删除所有$stmt2时,它工作得很好。我试图将“活动”列更改为零。基本上试图搜索和更新用户上传的所有其他图片并将其更改为零(因此它不是个人资料图片),只有最近的一张应该是活动的($active中的1)。

  • 可能重复: dbcp中的已准备语句池 我正在构建一个Web应用程序,它使用Tomcat的数据库连池机制进行内部使用。我试图汇集准备好的语句,以便应用程序在检索数据时更有效。 据我所知,当连接、结果集和语句关闭时,连接将返回到池。如果设置了适当的标志,放弃的连接也会关闭并返回到池中。关闭连接意味着释放所有数据库游标和缓存的语句,包括准备好的语句。那么准备好的语句池有什么意义呢?