Pipeline()返回$response
回顾:完成bootstrap()后终于要获取$response了
//Illuminate\Foundation\Http\Kernel
public function handle($request)
{
$request->enableHttpMethodParameterOverride();
$response = $this->sendRequestThroughRouter($request);
$this->app['events']->dispatch(
new Events\RequestHandled($request, $response)
);
return $response;
}
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());
}
Pipeline
namespace Illuminate\Routing;
use Illuminate\Pipeline\Pipeline as BasePipeline;
class Pipeline extends BasePipeline
{
protected function carry()
{
return function ($stack, $pipe) {
return function ($passable) use ($stack, $pipe) {
$slice = parent::carry();
$callable = $slice($stack, $pipe);
return $callable($passable);
};
};
}
}
namespace Illuminate\Pipeline;
use Illuminate\Contracts\Pipeline\Pipeline as PipelineContract;
class Pipeline implements PipelineContract
{
protected $container;
protected $passable;
protected $pipes = [];
protected $method = 'handle';
public function __construct(Container $container = null)
{
$this->container = $container;
}
public function send($passable)
{
$this->passable = $passable;
return $this;
}
public function through($pipes)
{
$this->pipes = is_array($pipes) ? $pipes : func_get_args();
return $this;
}
public function then(Closure $destination)
{
$pipeline = array_reduc
array_reverse($this->pipes), $this->carry(), $this->prepareDestination($destination)
);
return $pipeline($this->passable);
}
}
动作解析
(new Pipeline($this->app))//container属性引用服务容器
->send($request)//passable引用$request实例
->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)//pipes赋值中间件
->then($this->dispatchToRouter());//核心动作,将中间件类名以use关键字存储在匿名函数中,递归执行
then()
public function then(Closure $destination)
{
$pipeline = array_reduce(
array_reverse($this->pipes), $this->carry(), $this->prepareDestination($destination)
);
return $pipeline($this->passable);
}
$this->pipes:
array:5 [▼
0 => "Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode"
1 => "Illuminate\Foundation\Http\Middleware\ValidatePostSize"
2 => "App\Http\Middleware\TrimStrings"
3 => "Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull"
4 => "App\Http\Middleware\TrustProxies"
]
array_reverse($this->pipes):将数组反转,因为$pipeline匿名函数对中间件对存储是先今后出
$this->carry()返回匿名函数
//class Illuminate\Routing\Pipeline
function ($stack, $pipe) {
return function ($passable) use ($stack, $pipe) {
$slice = parent::carry();
$callable = $slice($stack, $pipe);
return $callable($passable);
};
};
$this->prepareDestination($destination)返回
function ($request) {
$this->app->instance('request', $request);
return $this->router->dispatch($request);
};
array_reduce ( array $array , callable $callback [, mixed $initial = NULL ] )
这个函数将数组的值遍历通过回调函数处理,最终返回一个值
callback ( mixed $carry , mixed $item ) : mixed
$carry:之前迭代的值
$item:本次迭代的值
回到then()
//class Illuminate\Pipeline\Pipeline;
public function then(Closure $destination)
{
//carry()才是动作的核心,当前执行的是Illuminate\Routing\Pipeline carry()
$pipeline = array_reduce(
array_reverse($this->pipes), $this->carry(), $this->prepareDestination($destination)
);
return $pipeline($this->passable);
}
//class Illuminate\Routing\Pipeline
function ($stack, $pipe) {
return function ($passable) use ($stack, $pipe) {
$slice = parent::carry();
$callable = $slice($stack, $pipe);
return $callable($passable);
};
};
//class Illuminate\Pipeline\Pipeline;
protected function carry()
{
return function ($stack, $pipe) {
return function ($passable) use ($stack, $pipe) {
list($name, $parameters) = $this->parsePipeString($pipe);
$pipe = $this->getContainer()->make($name);
$parameters = array_merge([$passable, $stack], $parameters);
return method_exists($pipe, $this->method)
? $pipe->{$this->method}(...$parameters)
: $pipe(...$parameters);
};
};
}
这里在处理数组的过程中,最初$stack 为dispatchToRouter()返回的匿名函数,$pipe为当前指针下数组的值,依次更新指针,依次返回匿名函数,每次匿名函数的关键在与use ($stack,$pipe),这里存储的是指针上一个位置返回的匿名函数和当前数组指针的值,其核心动作也是在档次执行的过程中使用$pipe参数执行当前动作,执行完毕后在执行$stack($parameters)最后执行dispatchToRouter();
Closure {#134 ▼
class: “Illuminate\Routing\Pipeline”
this: Pipeline {#30 …}
parameters: {▶}
use: {▶}
file: “/usr/local/var/www/auth/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php”
line: “49 to 61”
}
“Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull”
Closure {#131 ▼
class: “Illuminate\Routing\Pipeline”
this: Pipeline {#30 …}
parameters: {▶}
use: {▼
$stack: Closure {#134 …}
$pipe: “Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull”
}
file: “/usr/local/var/www/auth/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php”
line: “49 to 61”
}
“App\Http\Middleware\TrimStrings”
Closure {#133 ▼
class: “Illuminate\Routing\Pipeline”
this: Pipeline {#30 …}
parameters: {▶}
use: {▼
$stack: Closure {#131 …}.
$pipe: “App\Http\Middleware\TrimStrings”
}
file: “/usr/local/var/www/auth/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php”
line: “49 to 61”
}
…
#133 : use $stack -> #131:use $stack -> #134…
这就是其执行过程了;我们看回调函数的执行吧!
public function then(Closure $destination)
{
$pipeline = array_reduce(
array_reverse($this->pipes), $this->carry(), $this->prepareDestination($destination)
);
//there ...
return $pipeline($this->passable);
}
$this->passable是$request实例,执行最终返回的匿名函数,将$request作为参数传递。
//class Illuminate\Routing\Pipeline
function ($stack, $pipe) {
return function ($passable) use ($stack, $pipe) {
$slice = parent::carry();//执行父类,返回匿名函数
$callable = $slice($stack, $pipe);//执行父类返回的匿名函数,再次返回匿名函数
return $callable($passable);//执行匿名函数
};
};
//class Illuminate\Pipeline\Pipeline;
protected function carry()
{
return function ($stack, $pipe) {
return function ($passable) use ($stack, $pipe) {
list($name, $parameters) = $this->parsePipeString($pipe);
$pipe = $this->getContainer()->make($name);//使用服务容器创建目标实例
$parameters = array_merge([$passable, $stack], $parameters);
//执行$pipe->handle();
return method_exists($pipe, $this->method)
? $pipe->{$this->method}(...$parameters)
: $pipe(...$parameters);
};
};
}
//handle()返回传递的匿名参数的执行结果,实现的效果类似递归执行匿名函数
public function handle($request, Closure $next)
{
...
return $next($request);
}
最终执行dispatchToRouter(),在这里才真正实现的路由解析的动作,不过,最近有点忙,就先到这里吧!等找到工作了空余时间我再更新路由解析的过程!