bwoebi bwoebi - 5 months ago 12
PHP Question

Using $this when not in object context with ReflectionFunction->invoke()

class someClass {
private $success = "success\n";
function getReflection() {
return new ReflectionFunction(function() {
print $this->success;
});
}
}
$reflection = (new someClass)->getReflection();
$reflection->invoke();


When I run this, I get a

Fatal error: Using $this when not in object context in Command line code on line 5


What's happening here? Why is
$this
not defined there...?

As I'm in a Closure inside a method,
$this
normally should be defined. And yes, I'm on a newer version than PHP 5.4.

How can I fix it?

Answer

ReflectionFunction is operating on unbound Closures. That's why after the ReflectionFunction::invoke() call, there's no defined $this variable inside the Closure and as such your fatal error appears.

But there's a way around it.

ReflectionFunction offers you three necessary methods to call it with the $this binding:

  • ReflectionFunctionAbstract::getClosure()
  • ReflectionFunctionAbstract::getClosureThis()
  • ReflectionFunctionAbstract::getClosureScopeClass()

The ReflectionFunctionAbstract::getClosure() is still unbound, but we can bind it via Closure::bind().

All Closure::bind() needs is the Closure, the wished object to be bound to and the class scope.

Then the solution is:

call_user_func(\Closure::bind(
    $reflection->getClosure(),
    $reflection->getClosureThis(),
    $reflection->getClosureScopeClass()->name));

I initially wanted to post this as a question only, but I had found the solution myself just before posting, so just adding the answer. Context was this issue: https://github.com/rdlowrey/Auryn/pull/72