laravel很多地方写的很精湛, 用少量代码实现复杂功能, 可谓非常精巧。比如路中间件的实现。

 

    /**
     * Get a Closure that represents a slice of the application onion.
     *
     * @return \Closure
     */
    protected function getSlice()
    {
        return function ($stack, $pipe) {
            return function ($passable) use ($stack, $pipe) {
                if ($pipe instanceof Closure) {
                    // If the pipe is an instance of a Closure, we will just call it directly but
                    // otherwise we'll resolve the pipes out of the container and call it with
                    // the appropriate method and arguments, returning the results back out.
                    return call_user_func($pipe, $passable, $stack);
                } elseif (! is_object($pipe)) {
                    list($name, $parameters) = $this->parsePipeString($pipe);

                    // If the pipe is a string we will parse the string and resolve the class out
                    // of the dependency injection container. We can then build a callable and
                    // execute the pipe function giving in the parameters that are required.
                    $pipe = $this->container->make($name);

                    $parameters = array_merge([$passable, $stack], $parameters);
                } else {
                    // If the pipe is already an object we'll just make a callable and pass it to
                    // the pipe as-is. There is no need to do any extra parsing and formatting
                    // since the object we're given was already a fully instantiated object.
                    $parameters = [$passable, $stack];
                }

                return call_user_func_array([$pipe, $this->method], $parameters);
            };
        };
    }

调用路由的地方:

    //这里的$pipes 是中间件名字, 或者 closure, 或者是个对象,  $firstSlice是个路由调用(里面执行正确的 controller action)
        return call_user_func(
            array_reduce($pipes, $this->getSlice(), $firstSlice), $this->passable
        );

这里的array_reduce, 实现了一个callback的堆栈, 将真正路由执行压在最下面。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注