Slim защитить призывников
В Slim Framework есть protect
функция, которая оборачивает вызываемые объекты внутри функции (т.е. другой вызываемый объект). Описание в руководстве говорит:
Что если вы хотите буквально сохранить замыкание как необработанное значение, а не вызывать его? Вы можете сделать это так:
$app->myClosure = $app->container->protect(function () {});
Глядя в исходный код, я вижу это:
/**
* Protect closure from being directly invoked
* @param Closure $callable A closure to keep from being invoked and evaluated
* @return Closure
*/
public function protect(\Closure $callable)
{
return function () use ($callable) {
return $callable;
};
}
Мне интересно, в чем смысл этого. Здесь я сделал свой собственный тест:
$foo = function() {
echo "Hello";
};
$bar = function () use ($foo) {
return $foo;
};
var_dump($foo);
var_dump($bar);
Вот что я получил:
object(Closure)#1 (0) {
}
object(Closure)#2 (1) {
["static"]=>
array(1) {
["foo"]=>
object(Closure)#1 (0) {
}
}
}
я могу позвонить $bar()
чтобы вернуть вызываемое, но зачем мне это делать, если я могу просто использовать $foo
? Может кто-нибудь объяснить, пожалуйста, цель этого?
1 ответ
Это все о замыканиях, вызываемых во время выполнения. Смысл этого становится очевидным, когда вам нужно использовать обратный вызов (передать закрытие как вызываемый \Closure
к другой функции) без немедленного его вызова.
Давайте посмотрим, что происходит внутри нашего Slim Run.
Так что, если мы просто назначаем закрытие для ресурса, например, так
$app->foo = function () {
return 'invoked foo returns this string';
};
или как синглтонский ресурс Slims
$app->container->singleton('foo', function () {
return 'invoked foo returns this string';
});
он будет вызываться при каждом вызове или при нашем первом вызове, соответственно... так
$app->foo;
вернет строку invoked foo returns this string
,
Допустим, мы хотим, чтобы другая функция использовала наш вызываемый объект (как некоторый промежуточный слой), и хотим вызвать его с помощью call_user_function()
, Таким образом, мы не хотим передавать вызываемую функцию (которая будет передавать возвращаемое значение), а скорее не вызывать закрытие, которое мы достигаем, назначая закрытие переменной / ресурсу, используя protect()
метод
$app->bar = $app->container->protect(function () {
return 'bar returns a callable closure';
});
И для демонстрации давайте передадим $app->foo
а также $app->bar
в call_user_function()
:
call_user_func($app->foo);
выдаст ошибку
"call_user_func() expects parameter 1 to be a valid callback,
function 'invoked foo returns this string' not found or invalid function name"
потому что он пытается вызвать возвращенную строку, где
call_user_func($app->bar);
вызывает закрытие, сохраненное в $app->bar
и возвращает свою возвращаемую строку, вот так:
"bar returns a callable closure"
Я надеюсь, что этот пример иллюстрирует полезность Slim protect()
метод.