[laravel源码]pipeline 解析

说明

本章说明 pipeline

源码

index.php
//1. 处理http请求
$response = $kernel->handle(
    $request = Illuminate\Http\Request::capture()
);

\Illuminate\Foundation\Http\Kernel.php
//2. handle内调用sendRequestThroughRouter
protected function sendRequestThroughRouter($request)
{
    $this->app->instance('request', $request);

    Facade::clearResolvedInstance('request');

    $this->bootstrap();

    //3. 实际的处理逻辑在Pipeline中
    return (new Pipeline($this->app))
    ->send($request)
    ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
    ->then($this->dispatchToRouter());
}

\Illuminate\Contracts\Pipeline
//4. Pipeline的接口定义
interface Pipeline
{
    //a.设置放入管道的对象
    public function send($traveler);
    //b.设置管道的节点,pipes 对应后面命名
    public function through($stops);
    //c.设置节点对应的方法名
    public function via($method);
    //d.设置最后的回调
    public function then(Closure $destination);
}

\Illuminate\Pipeline\Pipeline.php
文件中可以发现,最终的处理逻辑都在方法 then 中
public function then(Closure $destination)
{
    //主要逻辑是 $this->carry()对应的匿名函数,$this->prepareDestination()作为启动函数
    $pipeline = array_reduce(
    array_reverse($this->pipes), $this->carry(), $this->prepareDestination($destination)
    );

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

更精确是在方法 $this->carry(),下面有匿名函数的嵌套,看起来复杂,里面的重点在 $pipe
protected function carry()
{
    return function ($stack, $pipe) {
        return function ($passable) use ($stack, $pipe) {
            //pipe是否可执行
            if (is_callable($pipe)) {
                return $pipe($passable, $stack);
            //pipe是否是对象
            } elseif (! is_object($pipe)) {
                list($name, $parameters) = $this->parsePipeString($pipe);
                $pipe = $this->getContainer()->make($name);
                $parameters = array_merge([$passable, $stack], $parameters);
            } else {
                $parameters = [$passable, $stack];
            }
            //检测pipe是否有对应method,有则执行,没有则初始化
            $response = method_exists($pipe, $this->method)
            ? $pipe->{$this->method}(...$parameters)
            : $pipe(...$parameters);

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

//返回匿名函数作为 array_reduce 的初始值
protected function prepareDestination(Closure $destination)
{
    return function ($passable) use ($destination) {
        return $destination($passable);
    };
}

分析

  1. 顺着源码,pipe对应middleware,Router相关作为初始函数
  2. 整个框架的各个阶段
    1. 准备:根据配置创建对象app(容器),绑定各种对象(服务)
    2. 执行:顺序执行Router对应的回调,app绑定的middleware
本作品采用《CC 协议》,转载必须注明作者和本文链接
城里的野山参
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
文章
69
粉丝
10
喜欢
30
收藏
41
排名:571
访问:1.4 万
私信
所有博文
社区赞助商