Static Closures and PHP 7
| From: | Levi Morrison | Date: | Tue, 20 Jan 2015 17:58:29 +0000 |
| Subject: | Static Closures and PHP 7 | ||
| Groups: | php.internals | ||
| Request: | Send a blank email to internals+get-80882@lists.php.net to get a copy of this message | ||
Internals,
Last year I "fixed" the behavior of closures in a few regards, which
were included in PHP 5.5.14 and 5.6 (unsure on exact version):
- Static closures properly use late-static binding on
static::
calls from inside static methods.
- Non-static closures in static methods are automatically promoted
to static closures
The first item is undoubtably a bug-fix (see http://3v4l.org/lVenA for
an example).
The second item, however, is a bit more questionable. Take as an
example this code: http://3v4l.org/YMYeu (located at bottom of
email
as well). When in global scope using an anonymous function with a
$this->ptr does not error, but when we are in a static method there is
a warning at bind-time and a fatal when the method is called.
Before my changes I could have said this was a bug with confidence.
After my change, however, it means that the closure is implicitly
static and therefore cannot use a $this pointer. My patch didn't break
anything, but allowed people to use late static binding in non-static
closures inside of static methods (I recommend reading that sentence
again).
Logically, I am surprised by this behavior. I would think that
anything permissible for a closure in global scope is also permissible
for a closure in static scope.
What do you guys and gals think?
<?php
class A {
function hi() {
return "hello";
}
}
// in global scope
$f = function() {
return $this->hi(); // no warnings
};
$a = new A();
$g = $f->bindTo($a); // no warnings
echo $g(), PHP_EOL; // no warnings
class B extends A {
// in a static function
static function make() {
return function() {
return $this->hi(); // fatal error when called
};
}
}
$h = B::make();
$i = $h->bindTo($a); // warning
echo $i(), PHP_EOL; // fatal error