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(是第一次返回的闭包) $pip
(a::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 协议》,转载必须注明作者和本文链接
推荐文章: