Laravel 源码解读

最近想看看laravel的源代码,感觉头大,代码太多,层次太深,但是结构优美,语法基本代表php的标准,所以计划花点时间好好阅读一下,顺便记下笔记,以便随时查看。但是我计划先一个点一个点的弄懂,最后再做总结,可能顺序不太友好,本人能力有限,若理解不到位的地方,希望大神指点,或者喷都可以,本人内心强大,希望结交更多志同道合的朋友一起学习交流进步。

laravel pipline

简单介绍下中间件的作用过滤请求,长话短说,Illuminate\Foundation\Http\Kernel 里面的方法140行左右

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

        Facade::clearResolvedInstance('request');

        $this->bootstrap();

        return (new Pipeline($this->app))
                    ->send($request)
                    ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
                    ->then($this->dispatchToRouter());
    }

看send (设置初始请求对象也就是$request),through(就是要过滤的中间件类) 和 then (就是返回一个闭包函数)方法 最主要是then方法 大家可以去看看

public function then(Closure $destination)
    {
        $pipeline = array_reduce(
            array_reverse($this->pipes), $this->carry(), $this->prepareDestination($destination)
        );

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

laravel 的pipline 很巧妙 你可以用命令链模式去做pipline 但是laravel 巧妙地用到 array_reduce这个函数累积特性 加上i闭包函数的use 属性能保存作用域变量的特性,具体细节 我也不清楚,然后 我根据自己的理解 自己做了个例子

class a {
    public static function test($request,$next){
        return $next($request);
    }
}
class b {
    public static function test($request,$next){
        return $next($request);
    }
}
class c {
    public static function test($request,$next){
        return $next($request);
    }
}
$test = [a::class];
$prepareDestination = function ($a){var_dump($a);};
$pipline = array_reduce(
    array_reverse($test),
    function($stack,$pip){
        return function($passable) use($stack,$pip){
            print_r($static);
            $pip::test($passable, $stack);
        };
    },function($request)use($prepareDestination){$prepareDestination($request);});
    $pipline([1]);

我只是想用自己简单的例子去理解它的pipline 因为它的初次看起来很心慌,原理差不多
接下来我写一些上面的一段代码发生了什么,如果大家去自己写一个中间件的话

public function handle($request, Closure $next)
    {
        if (!$request->user()) {

        }
        return $next($request);
    }

这里的$next 其实就是闭包函数(上面的$pipline)只不过每次经过一个中间件处理后 $next($request),相当于执行上一次返回的闭包,废话少说,直接上图 或者代码
先让$test=[a::class];
然后我们 打印 $stack

例1
Closure Object
(
    [static] => Array
        (
            [prepareDestination] => Closure Object
                (
                    [parameter] => Array
                        (
                            [$a] => <required>
                        )

                )

        )

    [parameter] => Array
        (
            [$request] => <required>
        )

)

然后让$test = [a::class,b::clas]

例2
Closure Object
(
    [static] => Array
        (
            [stack] => Closure Object
                (
                    [static] => Array
                        (
                            [prepareDestination] => Closure Object
                                (
                                    [parameter] => Array
                                        (
                                            [$a] => <required>
                                        )

                                )

                        )

                    [parameter] => Array
                        (
                            [$request] => <required>
                        )

                )

            [pip] => b
        )

    [parameter] => Array
        (
            [$passable] => <required>
        )

)
Closure Object
(
    [static] => Array
        (
            [prepareDestination] => Closure Object
                (
                    [parameter] => Array
                        (
                            [$a] => <required>
                        )

                )

        )

    [parameter] => Array
        (
            [$request] => <required>
        )

)

然后可以在加上$test = [a::class,b::class,c::class]; 大家去打印看看

下面说明一下具体流程
当array_reduce 第一次执行时候时候 执行第二个参数闭包 注意 此时 use里面的 $stack(是第三个参数$prepareDestination) 和 $pip(倒转后第一个 b::class) ,执行后返回一个闭包,上面俩参数被保存起来了,接着执行第二次 注意此时的 use里面的 $stack(是第一次返回的闭包) $pipa::class) 然后又返回一个闭包,这个闭包里也保存着上面俩参数 。
其实最后得到的$pipline 就是一个闭包(第二次返回的闭包$stack保存着第一次返回的闭包依次类推)

$pipline = function($passable) use($stack,$pip){
            print_r($stack);
            //var_dump($pip);
            $pip::test($passable, $stack);
        }

不过此时$stack是一个闭包相当于例2 不过他的$stack是上一次返回的闭包,也等于

$stack = function($passable) use($stack,$pip){
            print_r($stack);
            //var_dump($pip);
            $pip::test($passable, $stack);
        }

不过此时的 use 里面的 $stack 参数 也是上一次返回的闭包,依次类推,直到我们默认的$prepareDestination闭包
最后当我们执行
$pipline([1])时候 里面的[1] 实际就是我们的$request, 也就执行里面的 $pip::test($passable, $stack); 注意此时的$pip 是 a类, $passable 是 [1] , $stack我们第一次返回的闭包例2,然后执行a 中的 return $next($request);· 此时 $next 就是我们第一次返回的闭包, 执行第一次返回的闭包 , 还记得第一次闭包里面的连参数保存的什么吗? 其实上面说过 $stack(第零次返回的闭包默认是第三个参数$prepareDestination) 和 $pip(倒转后第一个 b::class);所以一直执行下去;

最后总结一下 array_reduce 第一次生返回的闭包的俩use参数是默认的$prepareDestination和$test数组倒转后的第一个参数,array_reduce 第二次返回的闭包$pipline 的俩use参数是第一次返回的闭包和$test数组倒转后的第二个参数, 那么执行$pipline 的时候第一次$next($request)
相当于执行第一次的返回的闭包,第一次闭包里面也有$next($request) 相当于执行默认$prepareDestination 闭包; laravel 的原理跟这个差不多,这这是我自己的理解,理解有误希望多多指教。

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!