尝试理解 PHP array_map() 调用的奇怪变体

发布于 2024-11-02 09:17:08 字数 876 浏览 1 评论 0原文

我试图理解我找到开源 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() 使用?

I'm trying to understand some code I found the open source oauth-php library. The relevant code snippet is:

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);
}

Where $args is an array of arguments that contain variables intended for use in a formatted printing operation. I looked at the docs for array_map:

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

and the user comments and I did not see any use case where the first parameter in a call to array_map() was an array itself. In all the use cases I saw, the first parameter was either NULL or a (callback) function. It seems pretty obvious to me that the code takes the $args array and then builds a new array with the arguments sanitized by $this->sql_escape_string().

But the statement "array($this, 'sql_escape_string')" is throwing me since I would have expected simply '$this->sql_escape_string', or is that not a valid syntax? If so, how does wrapping $this and 'sql_escape_string' in an array create a valid callback function for array_map() to use?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

颜漓半夏 2024-11-09 09:17:08

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

array_map('sql_escape_string', $args);

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

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

应用 sql_escape_string() 方法来自 < code>$someClass$args 中的每个值。

It is actually passing the sql_escape_string method from the class itself as a callback. It is a way of clarifying ambiguous method calls. For example:

array_map('sql_escape_string', $args);

of course applies sql_escape_string() to each value in $args, whereas:

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

applies the sql_escape_string() method from $someClass to each value in $args.

无所谓啦 2024-11-09 09:17:08

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

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

如果它只是一个标量值,那么您就会这样做。但是您有一个数组,并且需要将该转义函数应用于 $args 数组的每个项目。因此,您需要实现 foreach 并应用该函数,或者使用带有 array_map 的单行代码。

The first parameter is a callback. It can be either a string or an array.

since I would have expected simply '$this->sql_escape_string'

You would if it were just one scalar value. But you have an array and you need to apply that escape function to each item of the $args array. So you need to implement foreach and apply that function or use one-liner with array_map.

戏剧牡丹亭 2024-11-09 09:17:08

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

它是有效的,但并不指代您认为它指代的内容。考虑自由函数、常量、类名和变量:每个都存在于不同的环境中(如果您愿意,也可以称为“命名空间”,但这很容易与 PHP 命名空间)。通过使用“$”作为 sigil:变量 $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);

当可调用引用可以时,闭包并不是那么有用,但总体上更强大。

But the statement "array($this, 'sql_escape_string')" is throwing me since I would have expected simply '$this->sql_escape_string', or is that not a valid syntax?

It's valid, but doesn't refer to what you think it refers to. Consider free functions, constants, class names and variables: each exists in different environments (or "namespaces" if you prefer, but that's easily confused with PHP namespaces). The different environment for variables is made explicit by the use of "$" as a sigil: the variable $foo versus the function foo(), constant foo and class Foo. This is also why constants and variables are case-sensitive, but functions and class names aren't: the different environments allow for different name resolution rules.

Similarly, object methods and properties exist in different environments. As a consequence, $this->sql_escape_string refers to a property, not a method. To confuse matters, that property could contain a callable, though such a callable couldn't be invoked directly:

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

As with constants and functions, properties and methods are distinguished by the absence or presence of an argument list.

If so, how does wrapping $this and 'sql_escape_string' in an array create a valid callback function for array_map() to use?

PHP's syntax for callable references goes beyond strings.

Free functions (functions not associated with a class or object; contrast with "bound functions") can unambiguously be referred to by their names. Static methods are bound to a class, but can be referred to with a string if it includes the class name (the syntax is "Class::method"). A string cannot contain enough information for an object method, however, since the method must be bound to a particular object, and PHP doesn't have a way to refer to an object using a string. The solution PHP's developers settled on was to use array syntax (as shown in the question sample code). They also included support for array syntax for static methods (array('Class', 'method')).

Besides callable references, callables can be closures. These offer an alternative way of passing object methods, but are more verbose and complex.

$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);

Closures aren't so useful when a callable reference will do, but are more powerful overall.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文