从PHP闭包中读取“ this”和“ use”参数

Mar*_*rty 3 php closures php-7.1

创建在PHP中返回闭包的方法时:

class ExampleClass {
  public function test() {
    $example = 10;

    return function() use ($example) {
      return $example;
    };
  }
}
Run Code Online (Sandbox Code Playgroud)

的结果print_r中包含this与(其方法创建的封闭件的类)static,它似乎是内结合的值use ()闭合的语句:

$instance = new ExampleClass();
$closure = $instance->test();

print_r($closure);
Run Code Online (Sandbox Code Playgroud)

生产:

Closure Object (
    [static] => Array (
        [example] => 10
    )
    [this] => ExampleClass Object()
)
Run Code Online (Sandbox Code Playgroud)

但是,我无法终生解决如何捕捉这些价值。在未收到以下内容的情况下,无法使用任何形式的属性访问器(例如$closure->static$closure->{'static'}):

PHP致命错误:未捕获错误:Closure对象在XYZ中不能具有属性。

数组访问符号显然也不起作用:

PHP致命错误:未捕获错误:无法在XYZ中将Closure类型的对象用作数组。

JSON编码对象,除了使值成为对象无用之外,还提供了一个空的JSON对象,{}并且使用ReflectionFunction该类无法访问这些项目。

封闭的文档不提供在所有或者访问这些值的任何手段。

除了做诸如输出缓冲和解析之类的可耻的事情之外print_r,我实际上看不到获得这些值的方法。

我是否缺少明显的东西?

注意:用例用于实现备忘录,这些值在识别呼叫是否与先前的缓存呼叫匹配时将非常有益。

Rog*_*Gee 5

看来您可能忽略了某些ReflectionFunction方法。

看一下ReflectionFunction::getClosureThis()方法。我通过搜索PHP zend_get_closure_this_ptr()中定义的来查找PHP 7源代码来进行跟踪zend_closures.c

该手册当前没有太多有关此功能的文档。我正在使用7.0.9; 尝试根据您的示例运行以下代码:

class ExampleClass {
  private $testProperty = 33;

  public function test() {
    $example = 10;

    return function() use ($example) {
      return $example;
    };
  }
}

$instance = new ExampleClass();
$closure = $instance->test();

print_r($closure);

$func = new ReflectionFunction($closure);
print_r($func->getClosureThis());
Run Code Online (Sandbox Code Playgroud)

您应该获得类似于以下内容的输出

Closure Object
(
    [static] => Array
        (
            [example] => 10
        )

    [this] => ExampleClass Object
        (
            [testProperty:ExampleClass:private] => 33
        )

)

ExampleClass Object
(
    [testProperty:ExampleClass:private] => 33
)
Run Code Online (Sandbox Code Playgroud)

关于闭包静态变量,这些变量返回ReflectionFunction::getStaticVariables()

php > var_dump($func->getStaticVariables());
array(1) {
  ["example"]=>
  int(10)
}
Run Code Online (Sandbox Code Playgroud)