Bug #66430 [Com]: ReflectionFunction::invoke does not invoke closure with object scope

From: Date: Wed, 21 Feb 2018 11:21:54 +0000
Subject: Bug #66430 [Com]: ReflectionFunction::invoke does not invoke closure with object scope
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-214061@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=66430&edit=1 ID: 66430 Comment by: westie at typefish dot co dot uk Reported by: westie at typefish dot co dot uk Summary: ReflectionFunction::invoke does not invoke closure with object scope Status: Open Type: Bug Package: Reflection related Operating System: All PHP Version: 5.5.7 Block user comment: N Private report: N New Comment: This issue is still a thing on PHP 7.1 Previous Comments: ------------------------------------------------------------------------ [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

« previous php.bugs (#214061) next »