1

在 Slim 框架中,有一个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?有人可以解释一下这样做的目的吗?

4

1 回答 1

2

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 \Closure to 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

$app->foo = function () {
    return 'invoked foo returns this string';
};

or as a Slims singleton resource

$app->container->singleton('foo', function () {
    return 'invoked foo returns this string';
});

it will be invoked on each call or on our first call to it, respectively ... so

$app->foo;

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 the protect() method

$app->bar = $app->container->protect(function () {
    return 'bar returns a callable closure';
});

And for a demonstration let's pass our $app->foo and $app->bar to call_user_function():

call_user_func($app->foo);

will throw an error

"call_user_func() expects parameter 1 to be a valid callback,
 function 'invoked foo returns this string' not found or invalid function name"

because it tries to invoke the returned string, where

call_user_func($app->bar);

calls the closure saved in $app->bar and returns its return string, like so:

"bar returns a callable closure"

I hope this example illustrates the usefulness of Slim's protect() method.

于 2015-01-31T18:31:03.063 回答