In Slim Framework, there is a protect function that wraps callables within a function (i.e. another callable). The description in the manual says:
What if you want to literally store a closure as the raw value and not have it invoked? You can do that like this:
$app->myClosure = $app->container->protect(function () {});
Looking into the source code, I see this:
/**
* 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;
};
}
I'm wondering what the point of that is. Here I did my own test:
$foo = function() {
echo "Hello";
};
$bar = function () use ($foo) {
return $foo;
};
var_dump($foo);
var_dump($bar);
This is what I got:
object(Closure)#1 (0) {
}
object(Closure)#2 (1) {
["static"]=>
array(1) {
["foo"]=>
object(Closure)#1 (0) {
}
}
}
I can call $bar() to return the callable but why would I do that if I can just use $foo? Can someone please explain the purpose of this?
It is all about closures being invoked on runtime. The point of it becomes apparent when you need to use a callback (pass a closure as callable
\Closureto another function) without immediately invoking it.Let's look what happens inside our Slim run.
So if we simply assign a closure to a resource, like so
or as a Slims singleton resource
it will be invoked on each call or on our first call to it, respectively ... so
will return the string
invoked foo returns this string.Lets say that we want another function to use our callable (as some kind of middle layer) and wants to invoke it with
call_user_function(). So we don't want to pass in the invoked function (which will be passing the returned value), but rather an uninvoked closure, which we achieve by assigning the closure to a variable/resource using theprotect()methodAnd for a demonstration let's pass our
$app->fooand$app->bartocall_user_function():will throw an error
because it tries to invoke the returned string, where
calls the closure saved in
$app->barand returns its return string, like so:I hope this example illustrates the usefulness of Slim's
protect()method.