Rquest

封装并拷贝了PHP的$_SERVER,$_COOKIE,$_POST,$_GET这些跟request相关的东西.

PipeLine 机制

首先理解pipeline机制,所有的pipeline机制都有类似的机理:

object-->[ stop1 -- > stop2 --> stop3 ->final stop] --> result

traveler: 传到pipeline的被处理的对象
stops: 每个pipeline节点的处理对象
method: 每个pipline的处理方法

接口:


interface Pipeline
{
    /**
     * Set the traveler object being sent on the pipeline.
     */
    public function send($traveler);

    /**
     * Set the stops of the pipeline.
     */
    public function through($stops);

    /**
     * Set the method to call on the stops.
     */
    public function via($method);

    /**
     * Run the pipeline with a final destination callback.
     */
    public function then(Closure $destination);
}

then是真正的调用, 就是1个reduce,PHP里是array_reduce,reduce确实是实现流水的最好方法,么有之一.

//D:\Projects\PHP\laravel\plus\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php
    public function then(Closure $destination)
    {
        $pipeline = array_reduce(
            array_reverse($this->pipes), $this->carry(), $this->prepareDestination($destination)
        );

        return $pipeline($this->passable);
    }

reduce数组的内容,即pipe可以是闭包,object, string:

then的每一步处理是:

1 pipe是闭包函数, 参数接受passable和当前处理的结果stack, 直接调用
    - 调用该闭包,返回结果

2 pipe是string, 取name和parameters出来;
    - name 可能已经注入过容器了,make出来再使用

3 pipe是object,不需要做什么

最后, 2 和 3 都调用pipe object里定义的handle方法 or 将pipe直接调用:(__invoke)
    protected function carry()
    {
        //reduce的执行函数,
        //array_reduce方法:
        //<https://www.php.net/manual/zh/function.array-reduce.php>
        //then处理的核心架构核心:reduce
        return function ($stack, $pipe) {
            //stack是上次迭代结果 ,是闭包,也就是下面这个return决定
            return function ($passable) use ($stack, $pipe) {
                if (is_callable($pipe)) {
                    // 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 $pipe($passable, $stack);
                } elseif (! is_object($pipe)) {
                    [$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->getContainer()->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];
                }

                //stack 都交给给了handle做参数, 真正的执行stack的地方还是handle
                $response = method_exists($pipe, $this->method)
                                ? $pipe->{$this->method}(...$parameters)
                                : $pipe(...$parameters);

                return $response instanceof Responsable
                            ? $response->toResponse($this->getContainer()->make(Request::class))
                            : $response;
            };
        };
    }

对应middleware里的handle:

    //对应上面的passable, stack
    public function handle($request, Closure $next) {
        $repsonse = $next($request);
        return $response;
    }

搞清楚了上面的pipeline机制,理解laravel的Middleware顺利成章:

 //D:\Projects\PHP\laravel\plus\vendor\laravel\framework\src\Illuminate\Foundation\Http
return (new Pipeline($this->app))
        //设定 request作为处理对象
        ->send($request)
        //设定 经过所有的middleware,也就是中间件,就是 pipeline里的元素
        // 每个middleware都会调用1次handle
        ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
        //最后的开始执行, 制定完毕交给router
        ->then($this->dispatchToRouter());

最后到router处理里去了:

     protected function dispatchToRouter()
    {
        return function ($request) {
            $this->app->instance('request', $request);

            return $this->router->dispatch($request);
        };
    }