Bug #66430 [Opn->Ver]: ReflectionFunction::invoke does not invoke closure with object scope
Edit report at https://bugs.php.net/bug.php?id=66430&edit=1
ID: 66430
Updated by: nikic@php.net
Reported by: westie at typefish dot co dot uk
Summary: ReflectionFunction::invoke does not invoke closure
with object scope
-Status: Open
+Status: Verified
Type: Bug
Package: Reflection related
Operating System: All
PHP Version: 5.5.7
Block user comment: N
Private report: N
Previous Comments:
------------------------------------------------------------------------
[2018-07-10 15:10:09] westie at typefish dot co dot uk
https://3v4l.org/rWFHv
To re-iterate, failing on all normal PHP versions yet working as expected on a third party PHP
implementation (HHVM)
------------------------------------------------------------------------
[2018-02-21 11:21:51] westie at typefish dot co dot uk
This issue is still a thing on PHP 7.1
------------------------------------------------------------------------
[2015-07-06 10:40:20] westie at typefish dot co dot uk
I have confirmed this issue is still a thing on versions 5.5.x and 5.6.x
------------------------------------------------------------------------
[2014-02-25 01:20:06] phplists at stanvassilev dot com
I've encountered the same issue. Very annoying.
The problem is that closures defined inside a class method are effectively "anonymous
methods" (since PHP 5.4).
When closures were introduced, the ReflectionFunction constructor was amended to accept either a
function name or a Closure instance.
Later $this for closures was added in 5.4, but ReflectionMethod didn't get the same treatment.
Something has to be done, either ReflectionMethod should support a closure instance where you
normally pass a method name, or ReflectionFunction should "remember" the object context.
The latter probably makes more sense, if also class Closure gains a method like, say, getBinding(),
which would mean we can write code like this:
// Return an object instance ("$this") for closures defined in object context.
// Returns a string with full class name for closures defined in static method context.
// Return null for closures defined in global and function context.
$binding = $closure->getBinding();
if ($thisBinding === null) {
$reflection = new \ReflectionFunction($closure);
} else {
$reflection = new \ReflectionMethod($binding, $closure);
}
Right now attempting to instantiate ReflectionMethod with a closure in any way causes only warnings
and fatal errors...
Just my thoughts. Thanks for reporting the problem, I hope we have a solution eventually.
------------------------------------------------------------------------
[2014-01-07 00:41:42] westie at typefish dot co dot uk
Description:
------------
Whenever you try to invoke a closure using ReflectionFunction, the object context that is bound to
it is not carried across, therefore execution fails.
This is broken for:
ReflectionFunction::invoke
ReflectionFunction::invokeArgs
The desired functionality can be obtained by:
Directly calling: $closure()
call_user_func($closure)
This happens when you ->bindTo a closure, or you get a closure for a method using
ReflectionMethod::getClosure().
Verified on PHP 5.4 latest dotdeb stable and 5.5 latest dotdeb stable.
Test script:
---------------
- http://ss.westie.sh/xpwa
Expected result:
----------------
outragebot@thor:~$ php ./bug.php
alpha.bravo: Valid representation
reflection of alpha.bravo: Valid representation
closure of alpha.bravo: Valid representation
call_user_func of closure: Valid representation
closure cl of c(alpha.bravo): Alpha
scope cl of c(alpha.bravo): Alpha
reflection of c(alpha.bravo): Valid representation
Actual result:
--------------
outragebot@thor:~$ php ./bug.php
alpha.bravo: Valid representation
reflection of alpha.bravo: Valid representation
closure of alpha.bravo: Valid representation
call_user_func of closure: Valid representation
closure cl of c(alpha.bravo): Alpha
scope cl of c(alpha.bravo): Alpha
reflection of c(alpha.bravo): PHP Fatal error: Using $this when not in object context in
/home/outragebot/bug.php on line 10
PHP Stack trace:
PHP 1. {main}() /home/outragebot/bug.php:0
PHP 2. ReflectionFunction->invoke() /home/outragebot/bug.php:32
PHP 3. Alpha::bravo() /home/outragebot/bug.php:32
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=66430&edit=1
Thread (7 messages)