Чтение аргументов "это" и "использовать" из закрытия PHP


При создании метода, возвращающего замыкание в PHP:

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

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

Результат print_r содержит this (класс, метод которого создал замыкание) и static, которые, по-видимому, являются значениями, связанными в операторе use () замыкания:

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

print_r($closure);

Производство:

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

Однако я ни за что на свете не смогу понять, как уловить эти ценности. Невозможно использовать любую форму доступа к свойствам (например, $closure->static или $closure->{'static'}) без получения следующее:

Неустранимая ошибка PHP: Неперехваченная ошибка: Объект закрытия не может иметь свойств в XYZ.

Нотация доступа к массиву, очевидно, также не работает:

Неустранимая ошибка PHP: Неперехваченная ошибка: Невозможно использовать объект типа Closure в качестве массива в XYZ.

JSON, кодирующий объект, помимо того, что делает значения бесполезными, если бы они были объектами, предоставляет пустой объект JSON {}, а использование класса ReflectionFunction не обеспечивает доступ к этим предметы.

Документация по закрытию также не предоставляет никаких средств доступа к этим значениям.

Помимо выполнения чего-то постыдного, такого как буферизация вывода и синтаксический анализ print_r или подобного, я на самом деле не вижу способа получить эти значения.

Я упускаю что-то очевидное?

Примечание: Вариант использования предназначен для реализации запоминания, и эти значения были бы чрезвычайно полезны для определения того, является ли вызов соответствует предыдущему кэшированному вызову.

Author: Marty, 2017-09-11

1 answers

Похоже, вы, возможно, упустили из виду некоторые методы ReflectionFunction.

Взгляните на ReflectionFunction::getClosureThis() метод. Я отследил это, просмотрев исходный код PHP 7, выполнив поиск zend_get_closure_this_ptr() который определяется в 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());

Вы должны получить результат, аналогичный к

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

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

)

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

Что касается статических переменных закрытия, они возвращаются с ReflectionFunction::getStaticVariables():

php > var_dump($func->getStaticVariables());
array(1) {
  ["example"]=>
  int(10)
}
 4
Author: Roger Gee, 2017-09-11 05:27:36