PHP 闭包:为什么匿名函数声明中的“静态”绑定到静态类时


php closures: why the 'static' in the anonymous function declaration when binding to static class?

php 文档中关于Closure::bind的示例包含匿名函数声明中的static。 为什么?如果将其删除,我找不到区别。

class A {
    private static $sfoo = 1;
}
$cl1 = static function() { // notice the "static"
    return self::$sfoo;
};
$bcl1 = Closure::bind($cl1, null, 'A');
echo $bcl1(); // output: 1

没有

class A {
    private static $sfoo = 1;
}
$cl1 = function() {
    return self::$sfoo;
};
$bcl1 = Closure::bind($cl1, null, 'A');
echo $bcl1(); // output: 1

我乞求不同。 的确,通常这并不重要。 但有时它很重要

包含对$this引用的闭包可能会阻止对该对象的垃圾回收,这反过来也可能显著影响性能。 这里有一个例子,它确实产生了巨大的差异:

class LargeObject {
    protected $array;
    public function __construct() {
        $this->array = array_fill(0, 2000, 17);
    }
    public function getItemProcessor(): Closure {
        // Try with and without 'static' here
        return static function () {
            // do some processing unrelated to $this
        };
    }
}
$start = microtime(true);
$processors = [];
for ($i = 0; $i < 2000; $i++) {
    $lo = new LargeObject();
    $processors[] = $lo->getItemProcessor();
}
$memory = memory_get_usage() >> 20;
$time = (microtime(true) - $start) * 1000;
printf("This took %dms and %dMB of memory'n", $time, $memory);

这是正常闭包的输出:

This took 55ms and 134MB of memory

下面是带有静态闭包的输出:

This took 22ms and 1MB of memory

我在 Debian Buster 上用 PHP 7.3.19 测试了这一点,所以 YMMV。 显然,这是一个专门构造的示例来演示差异。 但这样的事情也可能发生在实际应用中。 我开始使用 Slevomat 的 SlevomatCodingStandard.Functions.StaticClosure 嗅探来提醒我始终使用静态闭包。

发现了区别:你不能将静态闭包绑定到对象,只能改变对象范围。

class foo { }
$cl = static function() { };
Closure::bind($cl, new foo); // PHP Warning:  Cannot bind an instance to a static closure
Closure::bind($cl, null, 'foo') // you can change the closure scope

静态闭包与任何其他静态方法一样,无法访问$this

与任何其他方法一样,不访问$this的非静态闭包通常在静态上下文中工作。

正如你所注意到的,这并不重要。

这就像在类方法上使用 static 关键字一样。如果您不在方法中引用$this,则不一定需要它(尽管这确实违反了严格的标准)。

我想 PHP 可以解决你的意思是静态访问A Closure,因为第二个参数null bind()