2

我试图理解一些我发现开源 oauth-php 库的代码。相关的代码片段是:

protected function sql_printf ( $args )
{
    $sql  = array_shift($args);
    if (count($args) == 1 && is_array($args[0]))
    {
        $args = $args[0];
    }
    $args = array_map(array($this, 'sql_escape_string'), $args);
    return vsprintf($sql, $args);
}

其中 $args 是一个参数数组,其中包含用于格式化打印操作的变量。我查看了 array_map 的文档:

http://php.net/manual/en/function.array-map.php

和用户评论,我没有看到任何用例,其中调用 array_map() 的第一个参数是一个数组本身。在我看到的所有用例中,第一个参数要么是 NULL,要么是(回调)函数。对我来说很明显,代码采用 $args 数组,然后使用 $this->sql_escape_string() 清理的参数构建一个新数组。

但是语句“array($this, 'sql_escape_string')”让我很失望,因为我本来希望只是 '$this->sql_escape_string',或者这不是一个有效的语法?如果是这样,如何将 $this 和 'sql_escape_string' 包装在一个数组中创建一个有效的回调函数供 array_map() 使用?

——罗施勒

4

3 回答 3

3

它实际上是sql_escape_string从类本身作为回调传递方法。这是一种澄清模棱两可的方法调用的方法。例如:

array_map('sql_escape_string', $args);

当然适用sql_escape_string()于 中的每个值$args,而:

array_map(array($someClass, 'sql_escape_string'), $args);

sql_escape_string()方法from$someClass应用于 中的每个值$args

于 2011-04-20T00:59:01.397 回答
3

第一个参数是回调。它可以是字符串或数组。

因为我本来期望只是'$this->sql_escape_string'

如果它只是一个标量值,你会的。但是您有一个数组,您需要将该转义函数应用于$args数组的每个项目。因此,您需要实现foreach并应用该功能或​​将单线与array_map.

于 2011-04-20T00:59:50.277 回答
1

但是语句“array($this, 'sql_escape_string')”让我很失望,因为我本来希望只是 '$this->sql_escape_string',或者这不是一个有效的语法?

它是有效的,但并不指您认为它指的是什么。考虑自由函数、常量、类名和变量:每个都存在于不同的环境中(如果您愿意,也可以称为“命名空间”,但这很容易与PHP 命名空间混淆)。变量的不同环境通过使用“$”作为符号来明确表示:变量$foo与函数foo()、常量foo和类Foo。这也是为什么常量和变量区分大小写,而函数和类名不区分的原因:不同的环境允许不同的名称解析规则。

同样,对象方法和属性存在于不同的环境中。因此,$this->sql_escape_string指的是属性,而不是方法。令人困惑的是,该属性可能包含一个可调用对象,尽管不能直接调用这样的可调用对象:

class Foo {
    function frob() {return 23.0 / 42;}
}

$foo = new Foo;
$foo->frob = function () {return 0 / 0;};

$foo->frob(); # calls method, not closure function

$frob = $foo->frob;
$frob(); # oops: division by zero

与常量和函数一样,属性和方法的区别在于参数列表是否存在。

如果是这样,如何将 $this 和 'sql_escape_string' 包装在一个数组中创建一个有效的回调函数供 array_map() 使用?

PHP 的可调用引用语法超越了字符串。

自由函数(与类或对象无关的函数;与“绑定函数”相反)可以通过它们的名称明确引用。静态方法绑定到一个类,但如果它包含类名(语法为“Class::method”),则可以用字符串引用。但是,字符串不能包含对象方法的足够信息,因为方法必须绑定到特定对象,而 PHP 没有办法使用字符串来引用对象。PHP 开发人员确定的解决方案是使用数组语法(如问题示例代码所示)。它们还包括对静态方法 ( array('Class', 'method')) 的数组语法的支持。

除了可调用引用,可调用对象也可以是闭包。这些提供了一种传递对象方法的替代方式,但更加冗长和复杂。

$self = $this; # workaround: $this not accessible in closures before 5.4
$args = array_map(
    function ($value) use($self) {
        return $self->sql_escape_string($value);
    }, $args);

闭包在可调用引用的情况下不是很有用,但总体上更强大。

于 2013-08-04T22:34:07.277 回答