更深請求傳遞到應用程序(允許中間件「通行證」),只需調用$下一回調與$請求。 https://laravel.com/docs/5.4/middleware#defining-middleware
當Laravel正在處理的請求它運行堆棧中的所有適用的中間件。中間件可以設置爲在路由/控制器方法之前和/或之後運行。
爲了能夠做到這一點Laravel使用Illuminate\Pipeline\Pipeline
。本質上,它使用array_reduce
遍歷中間件棧然後返回一個Closure
來執行中間件。美容這個來自使用array_reverse
允許下一個中間件執行要傳遞到前一個。
更詳細地說明一點:
當Illuminate\Foundation\Http\[email protected]
被稱爲它建立了sendRequestThroughRouter
其中有以下的響應:
return (new Pipeline($this->app))
->send($request)
->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
->then($this->dispatchToRouter());
Pipeline
是Illuminate\Routing\Pipeline
延伸Illuminate\Pipeline\Pipeline
。
以上then()
方法基本上是:
->then(function ($request) {
$this->app->instance('request', $request);
return $this->router->dispatch($request);
})
那麼意味着我們開始了與接受最終結果一個閉合(在這一點請記住,關閉將不會被調用)。
然後,在then()
方法中,發生如上所述的array_reduce
和array_reverse
部分。
這裏是當then()
方法實際發生的一個簡單的例子(假設你知道array_reduce
是如何工作的):
function then(Closure $destination)
{
$pipeline = array_reduce(
array_reverse($this->middlewares),
//Remember $nextClosure is going to be the closure returned
//from the previous iteration
function ($nextClosure, $middlewareClass) {
//This is the $next closure you see in your middleware
return function ($request) use ($nextClosure, $middlewareClass) {
//Resolve the middleware
$middleware = app($middlewareClass);
//Call the middleware
return $middleware->{$this->method}($request, $nextClosure);
};
},
//The finial closure that will be called that resolves the destination
function ($request) use ($destination) {
return $destination($request);
}
);
return $pipeline($this->request);
}
說我們有3箇中間件:
[
One::class,
Two::class,
Three::class,
];
上面的變量$pipeline
基本上是:
function ($request) {
return app(One::class)->handle($request, function ($request) {
return app(Two::class)->handle($request, function ($request) {
return app(Three::class)->handle($request, function ($request) {
return $destination($request);
});
};);
};);
};
希望這會有所幫助!
查看代碼? –
這是堆棧中的下一個中間件關閉。 –
@MagnusEriksson查看問題的描述。我知道它的方法暗示了它的封閉性。我想知道的是handle()方法如何轉換爲閉包$ next。 –