PHP, замыкания и извлекающие параметры

#php #closures #anonymous-function

#php #замыкания #анонимная функция

Вопрос:

Я не уверен, как лучше всего это назвать, поэтому я подумал, что хотел бы опубликовать пример того, чего я пытаюсь достичь. На данный момент я очень упростил это.

Итак, сначала самый базовый класс, который будет выполнять действие.

 abstract class AuditedSave extends AuditedSaveImplementation
{

    public static function run($callback = null)
    {
        return new AuditedSaveImplementation($callback);
    }

}

class AuditedSaveImplementation
{

    public function __construct(Closure $closure)
    {
        echo ' - I ran before'; // point 1, $test = 0
        $closure();
        echo ' - i ran after!'; // point 2, $test = 1
    }

}
  

Затем код, который его вызывает.

 $test = 0;

AuditedSave::run(function() use ($test)
{
    $test = 1;
});
  

Таким образом, между пунктами 1 и 2, как указано в комментариях, выполняется замыкание и устанавливает значение $test равным 1. Однако я хочу сохранить значение того, что передается в качестве первого параметра (в данном случае $test ), как копию того, что было во время вызова функции, которая всегда будет выполняться, затем закрытие изменяет его (это та часть, которая может быть переменной), а затем послевыполняется сравнение, и действия выполняются на основе различий, которые всегда будут выполняться.

Однако, чтобы сделать это, мне нужно иметь доступ к переменной $test в __construct() методе AuditedSaveImplementation , не зная, как она называется.

Возможно ли это вообще?

Комментарии:

1. Нет, область действия $test — это нечто совершенно иное, чем AuditedSaveImplementation::__construct . Вам нужно переосмыслить все, что вы пытаетесь здесь сделать.

2. Невозможно. Передать в другой класс с соответствующей логикой (например getValue() , и / или getOriginalValue() ) вместо простого замыкания. Также $test всегда копируется в указанный вами код (ну, на самом деле это копирование при записи, но это не очень актуально). Его изменение не повлияет на исходную переменную.

Ответ №1:

Вы можете использовать метод класса ReflectionFunction getStaticVariables , чтобы получить параметры, переданные closure via use . Вот так:

 class AuditedSaveImplementation
{

    public function __construct(Closure $closure)
    {
        echo ' - I ran before'; // point 1, $test = 0
        $closureReflection = new ReflectionFunction($closure);
        $variables = $closureReflection->getStaticVariables();
        var_dump($variables);
        $closure();
        echo ' - i ran after!'; // point 2, $test = 1
    }

}
  

Но, как упоминалось в комментариях, вам следует переосмыслить, как вы это делаете.
Это не очень хороший подход. Попробуйте создать специальный класс, как было предложено в комментариях.

Комментарии:

1. Фу-у-у, это ужасное решение. Для этого должен быть разумный и простой интерфейс, а не перегибающее назад решение, которое зависит от деталей реализации. OP просто на неверном пути…

2. Я просто хотел показать, что это не невозможно. Что все, что передается в closure через use , будет преобразовано в статические переменные для замыкания и может быть извлечено с помощью отражения. Но я согласен, что автору нужно переосмыслить то, что он здесь делает.