嗯,我真的不知道为什么会发生这种行为。但有一个解决方法(好吧,我经过几次测试后发现它)。
由于PHP不要让你明确的$这个(it's bound automatically)绑定,你需要使用一个替代变量:
$t = $this;
$this->f = function() use ($t) {
return $t->x;
};
整个代码:
class Example {
private $x;
public $f;
public function __construct() {
$this->x = 10;
$t = $this;
$this->f = function() use ($t) {
return $t->x;
};
}
}
$ex = new Example();
$f = new ReflectionFunction($ex->f);
echo $f->invoke().PHP_EOL;
而结果想要
10
测试PHP 5.4,5.5,5.6和7.
UPDATE
MPEN的答案后,我意识到他的限制和实际使用反射。
当您使用ReflectionFunction调用至少是闭包的函数时,应该将其视为闭包。 ReflectionFunction有一个名为getClosure()的方法。
的类仍然是MPEN创建和使用将是:
$ex = new Example();
$f = new ReflectionFunction($ex->f);
$closure = $f->getClosure();
echo $closure().PHP_EOL;
但只适用于PHP 7
对于PHP 5.4,5.5和5.6,您需要绑定类范围。奇怪,但是是唯一的方法,我发现,使用Closure::bindTo()或Closure::bind():
$ex = new Example();
$f = new ReflectionFunction($ex->f);
$closure = $f->getClosure();
$class = $f->getClosureThis();
$closure = $closure->bindTo($class , $class);
echo $closure().PHP_EOL;
或者只是:
$ex = new Example();
$f = new ReflectionFunction($ex->f);
$class = $f->getClosureThis();
$closure = Closure::bind($f->getClosure() , $class , $class);
echo $closure().PHP_EOL;
这是版本关口班级为范围(第二个参数),这将决定是否您可以访问私有/受保护的变量或不。
第二paramater也可以是类名称为:
$closure = $closure->bindTo($class , 'Example');//PHP >= 5.4
$closure = $closure->bindTo($class , get_class($class));//PHP >= 5.4
$closure = $closure->bindTo($class , Example::class);//PHP 5.5
但我没有在意性能,因此通过两次的类一样好给我。
还有可以用来改变的范围的方法Closure::call(),也只是为PHP> = 7
谢谢,但这不是真正的我一个解决方案。我需要能够调用任意关闭。 – mpen
@mpen我已经更新了所有我测试过的问题 –