TransWikia.com

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

Stack Overflow Asked by learning php on December 30, 2021

The example in the php documentation on Closure::bind include static on the anonymous function declaration. why? I can’t find the difference if it is removed.

with:

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

without:

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

4 Answers

I beg to differ. It's true that often it won't matter. But sometimes it matters a whole lot.

The closure holding a reference to $this might prevent garbage collection of that object, which in turn may also impact performance significantly. Here's an example where it really makes a huge difference:

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 memoryn", $time, $memory);

Here's the output with a normal closure:

This took 55ms and 134MB of memory

Here's the output with a static closure:

This took 22ms and 1MB of memory

I tested this with PHP 7.3.19 on Debian Buster, so YMMV. Obviously this is a specially constructed example to demonstrate the difference. But things like this may happen in real applications as well. I started using Slevomat's SlevomatCodingStandard.Functions.StaticClosure sniff to remind me to always use static closures.

Answered by jlh on December 30, 2021

Static Closures, like any other static method, cannot access $this.

Like any other method, a non-static Closure that does not access $this will generally work in a static context.

Answered by Hendrik Rombach on December 30, 2021

found the difference: you can't bind static closures to object, only change the object scope.

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

Answered by learning php on December 30, 2021

As you've noticed, it doesn't really matter.

It's like using the static keyword on a class method. You don't necessarily need it if you don't reference $this within the method (though this does violate strict standards).

I suppose PHP can work out you mean the Closure to access A statically due to the null 2nd argument to bind()

Answered by Phil on December 30, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP