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
Am 20.01.2015 um 18:58 schrieb Levi Morrison:
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 closuresThe 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?
It should indeed have the same object behavior as closures in global scope.
Before bind: "Fatal error: Using $this when not in object context"
After bind: valid
But "static::" and "self::" should work the same as on static closures.
<?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 warningsclass 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
Marc