前言
本文主要給大家介紹的是關(guān)于Laravel路由模塊的相關(guān)內(nèi)容,分享出來(lái)供大家參考學(xué)習(xí),下面話不多說(shuō)了,來(lái)一起看看詳細(xì)的介紹吧。
備注:本文是基于Laravel 5.4版本的路由模塊代碼進(jìn)行分析書寫;
模塊組成
下圖展示了路由模塊中各個(gè)文件的關(guān)系,并進(jìn)行簡(jiǎn)要說(shuō)明;
剖析
服務(wù)提供者
看Laravel模塊,首先找ServiceProvider文件,這是模塊與IOC容器交互的入口,從這個(gè)文件,可以看出該模塊提供向系統(tǒng)提供了哪些服務(wù);
public function register() { // 注冊(cè)路由管理,提供路由注冊(cè),路由匹配的功能 $this->registerRouter(); // 注冊(cè) Url 生成器實(shí)例 $this->registerUrlGenerator(); // 注冊(cè)跳轉(zhuǎn)器 $this->registerRedirector(); // 綁定 PSR-7 請(qǐng)求實(shí)現(xiàn)到 ServerRequestInterface 接口 $this->registerPsrRequest(); // 綁定 PSR-7 Response 實(shí)現(xiàn)到 ResponseInterface 接口 $this->registerPsrResponse(); // 注冊(cè) ReponseFactory,提供各式各樣的 Response,比如視圖響應(yīng)、Json響應(yīng)、Jsonp響應(yīng)、文件下載等 $this->registerResponseFactory(); }
路由管理
“路由管理”服務(wù)有以下元素需要了解:
- Route:路由;會(huì)記錄 Url、Http 動(dòng)作、Action (路由要執(zhí)行的具體對(duì)象,可能是 Closure,也可以是某個(gè) Controller 中的方法),路由參數(shù),路由參數(shù)的約束;
- RouteCollection:路由集,用來(lái)存儲(chǔ)所有Route對(duì)象的“盒子”;
- RouteGroup:路由組;只有路由注冊(cè)過程中會(huì)臨時(shí)用到;存儲(chǔ)一批路由公共的一些屬性,屬性包括domain、prefix、as、middleware、namespace、where;
- Resource:資源路由;資源路由是一套路由的統(tǒng)稱,包含列表(index)、顯示增加(create)、保存增加(store)、顯示詳情(show)、顯示編輯詳情(edit)、更新編輯(update)、刪除詳情(destory);同時(shí)可以通過調(diào)用only或except方法或參數(shù)的形式只生成部分路由;
- Action:路由要執(zhí)行的對(duì)象;有兩種表現(xiàn)形式,一是Closure函數(shù),二是類似
['uses' => 'FooController@method', 'as' => 'name']
這樣的字符串;對(duì)于不同的表現(xiàn)形式,路由在執(zhí)行時(shí)會(huì)調(diào)用不同的處理;
注冊(cè)流程
在項(xiàng)目啟動(dòng)后,會(huì)執(zhí)行所有ServiceProvider的loadRoutes方法,也就是調(diào)用map方法,一般情況下map方法如下
public function map(Router $router){ require __DIR__.'/routes.php'; }
這時(shí)候,項(xiàng)目就會(huì)執(zhí)行很多Route::get
、Route::post
、Route::group
方法;
當(dāng)遇到Route::group方法時(shí),會(huì)實(shí)例化一個(gè)RouteGroup對(duì)象,put進(jìn)Router管理類的路由組棧頭部;而后當(dāng)執(zhí)行g(shù)et、post這類具體的注冊(cè)路由方法時(shí),會(huì)把當(dāng)前路由組棧中所有組的屬性合并進(jìn)新路由中,將新路由存儲(chǔ)在RouteCollection這個(gè)大盒子里;當(dāng)Route::group的Closure執(zhí)行完畢時(shí),會(huì)把頭部的RouteGroup實(shí)例pull出去;
當(dāng)執(zhí)行Route::resource時(shí),Router管理類會(huì)調(diào)用ResourceRegister類來(lái)完成批量注冊(cè)路由;
對(duì)于 Router::get這類注冊(cè)方法,Illuminate\Foudation\helpers提供了簡(jiǎn)寫;
Router::get
簡(jiǎn)化成 get,Router::post
簡(jiǎn)化成 post,Router::put
簡(jiǎn)化成 put,Router::patch
簡(jiǎn)化成 patch,Router::delete
簡(jiǎn)化成 delete,Router::resource
簡(jiǎn)化成 resource,
至此,RouteCollection大盒子就存放了所有要注冊(cè)的路由;
request 請(qǐng)求匹配流程
首先,request請(qǐng)求會(huì)經(jīng)過Foundation/Http/Kernel的handle方法,在這個(gè)方法中,請(qǐng)求會(huì)執(zhí)行以下語(yǔ)句
$this->router->dispatch($request)
這里的$this->router
,就是Router管理類;dispatch方法如下
public function dispatch(Request $request) { $this->currentRequest = $request; return $this->dispatchToRoute($request); } public function dispatchToRoute(Request $request) { // 根據(jù)請(qǐng)求的 url 找到匹配的路由 $route = $this->findRoute($request); // 將路由綁定到請(qǐng)求上 $request->setRouteResolver(function () use ($route) { return $route; } // 觸發(fā) RouteMatched 事件 $this->events->dispatch(new Events\RouteMatched($route, $request)); // 通過 Pipeline 流水線執(zhí)行路由上綁定的中間件及對(duì)應(yīng)的方法 $response = $this->runRouteWithinStack($route, $request); // 根據(jù) request 請(qǐng)求設(shè)置 response 的響應(yīng)頭 return $this->prepareResponse($request, $response); }
1、根據(jù)請(qǐng)求找匹配的路由