[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);
};
}
分析
- 顺着源码,pipe对应middleware,Router相关作为初始函数
- 整个框架的各个阶段
- 准备:根据配置创建对象app(容器),绑定各种对象(服务)
- 执行:顺序执行Router对应的回调,app绑定的middleware
本作品采用《CC 协议》,转载必须注明作者和本文链接