Laravel學(xué)習(xí)教程之路由模塊
前言
本文主要給大家介紹的是關(guān)于Laravel路由模塊的相關(guān)內(nèi)容,分享出來供大家參考學(xué)習(xí),下面話不多說了,來一起看看詳細(xì)的介紹吧。
備注:本文是基于Laravel 5.4版本的路由模塊代碼進(jìn)行分析書寫;
模塊組成
下圖展示了路由模塊中各個(gè)文件的關(guān)系,并進(jìn)行簡要說明;
剖析
服務(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:路由集,用來存儲(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類來完成批量注冊(cè)路由;
對(duì)于 Router::get這類注冊(cè)方法,Illuminate\Foudation\helpers提供了簡寫;
Router::get
簡化成 get,Router::post
簡化成 post,Router::put
簡化成 put,Router::patch
簡化成 patch,Router::delete
簡化成 delete,Router::resource
簡化成 resource,
至此,RouteCollection大盒子就存放了所有要注冊(cè)的路由;
request 請(qǐng)求匹配流程
首先,request請(qǐng)求會(huì)經(jīng)過Foundation/Http/Kernel的handle方法,在這個(gè)方法中,請(qǐng)求會(huì)執(zhí)行以下語句
$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)求找匹配的路由
`RouteCollection`根據(jù)請(qǐng)求的`http`動(dòng)作縮小要匹配的路由范圍;在篩選出來的這些路由中依次遍歷,找出第一個(gè)符合驗(yàn)證的路由(需要進(jìn)行較驗(yàn)的驗(yàn)證在`Route`中的`getValidators`方法中聲明);
2、將路由綁定到請(qǐng)求上
3、觸發(fā)RouteMatched事件
初始化的`Laravel`項(xiàng)目沒有對(duì)`RouteMatched`路由匹配事件進(jìn)行任何的監(jiān)聽器綁定,如有需要,可以自定義監(jiān)聽器,在模塊的`EventServiceProvider`中注冊(cè)該事件監(jiān)聽;這樣一旦請(qǐng)求匹配上某個(gè)路由,就可以執(zhí)行自定義方法了;
4、通過 Pipeline 流水線執(zhí)行路由上綁定的中間件及對(duì)應(yīng)的方法
在`runRouteWithinStack`方法中,系統(tǒng)會(huì)判斷是否需要執(zhí)行中間件,如果`IOC`容器中設(shè)置了`middleware.disable`的值為`true`,則需要執(zhí)行的中間件數(shù)組為空;否則會(huì)找到所有的中間件,并按照`middlewarePriority`對(duì)必要的一些中間件進(jìn)行排序調(diào)整;然后執(zhí)行`$route->run()`
方法;
5、根據(jù) request 請(qǐng)求設(shè)置 response 的響應(yīng)頭
項(xiàng)目中會(huì)用到的一些方法
- 獲取路由集合
app('router')->getRoutes()
- 獲取當(dāng)前的請(qǐng)求
$request = app('router')->getCurrentRequest()
- 獲取當(dāng)前請(qǐng)求所對(duì)應(yīng)的路由
$route = $request->route() 或 $route = app('router')->getCurrentRoute()
- 獲取當(dāng)前路由需要執(zhí)行的中間件
$middlewares = app('router')->gatherRouteMiddleware($route)
Url 生成器
Url 生成器是什么?
舉個(gè)例子,
$url = new UrlGenerator( $routes = new RouteCollection, $request = Request::create('http://www.foo.com/') ); $url->to('foo/bar'); // 輸出 http://www.foo.com/foo/bar
像這種基于當(dāng)前請(qǐng)求,生成指定路徑的Url;
這部分功能由兩個(gè)文件完成,一個(gè)是UrlGenerator.php,另一個(gè)是RouteUrlGenerator.php;UrlGenerator.php處理根據(jù)路徑名生成Url,RouteUrlGenerator.php處理根據(jù)路由生成Url;
列一些常用的使用:
根據(jù)路徑名生成
使用to方法,第一個(gè)參數(shù)為路徑,第二個(gè)參數(shù)是數(shù)組,implode后會(huì)接著路徑名,第三個(gè)參數(shù)決定用不用https
// 路徑名是 foo/bar,當(dāng)前請(qǐng)求的根路徑為 http://www.foo.com,所以輸出是 http://www.foo.com/foo/bar $url->to('foo/bar') // 路徑名是 foo/bar,當(dāng)前請(qǐng)求的根路徑為 http://www.foo.com,第三個(gè)參數(shù)決定 scheme 是 https,所以輸出是 https://www.foo.com/foo/bar $url->to('foo/bar', [], true) // 路徑名是 foo/bar,第二個(gè)參數(shù) 是補(bǔ)充路徑名,implode 后是 /baz/boom // 第三個(gè)參數(shù)決定 scheme 是 https,所以輸出是 https://www.foo.com/foo/bar/baz/boom $url->to('foo/bar', ['baz', 'boom'], true) // 路徑名是 foo/bar,查詢參數(shù)是 ?foo=bar ,補(bǔ)充路徑是 /baz,所以輸出是 https://www.foo.com/foo/bar/baz?foo=bar $url->to('foo/bar?foo=bar', ['baz'], true)
根據(jù)路由的 as 名生成
使用route方法,第一個(gè)參數(shù)為指定路由的 as 名,第二個(gè)參數(shù)是參數(shù)數(shù)組,第三個(gè)參數(shù)決定是否顯示根目錄(默認(rèn)為 true)
$route = new Route(['GET'], 'foo/bar', ['as' => 'foo']); $routes->add($route); // 輸出 'http://www.foo.com/foo/bar $url->route('foo'); // 第三個(gè)參數(shù)為 false,表示不顯示根目錄,于是輸出 /foo/bar $url->route('foo', [], false) // 路由中的 url 本身不帶參數(shù),則第二參數(shù)中所有關(guān)聯(lián)數(shù)組都將作為查詢參數(shù) // 輸出 /foo/bar?foo=bar $url->route('foo', ['foo' => 'bar'], false)
$route = new Route(['GET'], 'foo/bar/{baz}/breeze/{boom}', ['as' => 'bar']); $routes->add($route); // 路由上的 url 帶參數(shù),根據(jù)參數(shù)名找值;剩余多余的為查詢參數(shù); // 輸出 http://www.foo.com/foo/bar/otwell/breeze/taylor?fly=wall $url->route('bar', ['boom' => 'taylor', 'baz' => 'otwell', 'fly' => 'wall']); // 路由上的 url 帶參數(shù),找不到對(duì)應(yīng)的參數(shù)值,則按順序作值;剩余多余的為查詢參數(shù); // 輸出 http://www.foo.com/foo/bar/taylor/breeze/otwell?fly=wall $url->route('bar', ['taylor', 'otwell', 'fly' => 'wall']);
根據(jù)路由的 action 名生成
使用action方法,第一個(gè)參數(shù)為指定路由的 action 名,第二個(gè)參數(shù)是參數(shù)數(shù)組,第三個(gè)參數(shù)決定是否顯示根目錄(默認(rèn)為 true)
$route = new Route(['GET'], 'foo/bam', ['controller' => 'foo@bar']); $routes->add($route); // 輸出 http://www.foo.com/foo/bam $url->action('foo@bar');
$route = new Route(['GET'], 'foo/invoke', ['controller' => 'InvokableActionStub']); $routes->add($route); // 輸出 http://www.foo.com/foo/invoke $url->action('InvokableActionStub');
設(shè)置全局默認(rèn)參數(shù)
$url->defaults(['locale' => 'en']); $route = new Route(['GET'], 'foo', ['as' => 'defaults', 'domain' => '{locale}.example.com', function() {}]); // 路由 url 有參數(shù),但沒有傳參數(shù)值,則會(huì)找全局默認(rèn)參數(shù)值;輸出 http://en.example.com/foo $url->route('defaults');
設(shè)置全局命名空間
這樣調(diào)用的時(shí)候,不用在 action 上省略這部分命名空間
// 設(shè)置全局命名空間 $url->setRootControllerNamespace('namespace'); // 配置添加路由 $route = new Route(['GET'], 'foo/bar', ['controller' => 'namespace\foo@bar']); $routes->add($route); $route = new Route(['GET'], 'foo/invoke', ['controller' => 'namespace\InvokableActionStub']); $routes->add($route); // 輸出 http://www.foo.com/foo/bar; action 的值省略 namespace 這個(gè)命名空間 $url->action('foo@bar'); // 輸出 http://www.foo.com/foo/invoke; action 的值省略 namespace 這個(gè)命名空間 $url->action('InvokableActionStub'); // 配置添加路由 $route = new Route(['GET'], 'something/else', ['controller' => 'something\foo@bar']); $routes->add($route); // 輸出 http://www.foo.com/something/else; action 的最前面加了 `\`,全局命名空間下調(diào)用 $url->action('\something\foo@bar');
跳轉(zhuǎn)器
跳轉(zhuǎn)器內(nèi)部提供了以下跳轉(zhuǎn);
home
通過調(diào)用app('redirect')->home()
會(huì)跳轉(zhuǎn)至根目錄下\;
public function home($status = 302)
back
通過調(diào)用app('redirect')->back()
會(huì)跳轉(zhuǎn)至上一次訪問頁面;或者全局幫助函數(shù)back()
也可以;
public function back($status = 302, $headers = [], $fallback = false)
第三個(gè)參數(shù)表示,如果沒有前一次訪問請(qǐng)求,訪問哪個(gè)頁面,具體源碼如下:
if ($url) { return $url; } elseif ($fallback) { return $this->to($fallback); } else { return $this->to('/'); }
refresh
通過調(diào)用app('redirect')->refresh()
會(huì)刷新當(dāng)前訪問頁面;
public function refresh($status = 302, $headers = [])
to
通過調(diào)用app('redirect')->to('path')
會(huì)跳轉(zhuǎn)至指定路徑頁面;或者全局幫助函數(shù)redirect('path')
也可以;
這里的 path 路徑是不包含根目錄的,例如(foo/bar);
public function to($path, $status = 302, $headers = [], $secure = null)
第四個(gè)參數(shù)表示是否使用https;
away
通過調(diào)用app('redirect')->away('path')
會(huì)跳轉(zhuǎn)至指定路徑頁面;
這里的 path 路徑是包含根目錄的,例如(http://xx.com/foo/bar);
public function away($path, $status = 302, $headers = [])
secure
通過調(diào)用app('redirect')->secure('path')
會(huì)跳轉(zhuǎn)至指定路徑頁面;這里的path路徑是不包含根目錄的;
public function secure($path, $status = 302, $headers = [])
其本質(zhì)是調(diào)用了to方法
return $this->to($path, $status, $headers, true);
route
通過調(diào)用app('redirect')->route('route_as_name')
,根據(jù)路由的as名會(huì)跳轉(zhuǎn)至與路由一致的url路徑頁;
public function route($route, $parameters = [], $status = 302, $headers = [])
action
通過調(diào)用app('redirect')->action('route_action')
,根據(jù)路由的action名會(huì)跳轉(zhuǎn)至與路由一致的url路徑頁;
public function action($action, $parameters = [], $status = 302, $headers = [])
guest
跳到指定的路徑頁的同時(shí),將當(dāng)前url存放至session中,鍵名為url.intended;
public function guest($path, $status = 302, $headers = [], $secure = null)
intended
跳轉(zhuǎn)至session中鍵名為url.intended的值所對(duì)應(yīng)的Url;如果不存在,則跳轉(zhuǎn)至第一個(gè)參數(shù)所傳的值;
public function intended($default = '/', $status = 302, $headers = [], $secure = null)
響應(yīng)工廠(ResponseFactory)
ResponseFactory文件提供了兩部分 API,分別是與響應(yīng)類型相關(guān)和與跳轉(zhuǎn)相關(guān);
響應(yīng)
response()
會(huì)返回ResponseFactory實(shí)例;
視圖響應(yīng)
response()->view('hello', $data, 200);
Jsop響應(yīng)
response()->json(['name' => 'Abigail', 'state' => 'CA']);
Jsonp響應(yīng)
response()->json(['name' => 'Abigail', 'state' => 'CA'])->withCallback($request->input('callback'));
文件響應(yīng)
直接在瀏覽器顯示文件,而不是下載,例如圖片或PDF;file方法第一參數(shù)為文件路徑,第二參數(shù)選填為頭信息數(shù)組;
response()->file($pathToFile, $headers);
文件下載
download方法第一參數(shù)為文件路徑,第二參數(shù)選填為文件名,第三參數(shù)選填為頭信息數(shù)組;
return response()->download($pathToFile, $name, $headers);
跳轉(zhuǎn)
這里的跳轉(zhuǎn)方法,其實(shí)調(diào)用的還是跳轉(zhuǎn)器中的方法,不過是在暴露更多的接口,方便調(diào)用與使用;
方法名 | 調(diào)用 | 實(shí)際調(diào)用的是跳轉(zhuǎn)器中的哪個(gè)方法 |
---|---|---|
redirectTo | response()->redirectTo(...) | to方法 |
redirectToRoute | response()->redirectToRoute(...) | route方法 |
redirectToAction | response()->redirectToAction(...) | action方法 |
redirectGuest | response()->redirectGuest(...) | guest方法 |
redirectToIntended | response()->redirectToIntended(...) | intended方法 |
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
- Laravel5.1 框架路由基礎(chǔ)詳解
- Laravel框架中的路由和控制器操作實(shí)例分析
- Laravel框架路由配置總結(jié)、設(shè)置技巧大全
- Laravel中獲取路由參數(shù)Route Parameters的五種方法示例
- Laravel最佳分割路由文件(routes.php)的方式
- 修改Laravel5.3中的路由文件與路徑
- Laravel 5框架學(xué)習(xí)之路由、控制器和視圖簡介
- Laravel框架模板加載,分配變量及簡單路由功能示例
- Laravel框架路由和控制器的綁定操作方法
- Laravel框架路由設(shè)置與使用示例
- laravel 配置路由 api和web定義的路由的區(qū)別詳解
- Laravel5.1框架路由分組用法實(shí)例分析
相關(guān)文章
ecshop實(shí)現(xiàn)smtp發(fā)送郵件
這篇文章主要介紹了ecshop實(shí)現(xiàn)smtp發(fā)送郵件,需要的朋友可以參考下2015-02-02thinkPHP框架實(shí)現(xiàn)的無限回復(fù)評(píng)論功能示例
這篇文章主要介紹了thinkPHP框架實(shí)現(xiàn)的無限回復(fù)評(píng)論功能,結(jié)合實(shí)例形式簡單分析了thinkPHP實(shí)現(xiàn)無限回復(fù)的相關(guān)控制器、視圖操作技巧,需要的朋友可以參考下2018-06-06PHP獲取IP地址所在地信息的實(shí)例(使用純真IP數(shù)據(jù)庫qqwry.dat)
下面小編就為大家?guī)硪黄狿HP獲取IP地址所在地信息的實(shí)例(使用純真IP數(shù)據(jù)庫qqwry.dat)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-11-11PHP使用CURL獲取302跳轉(zhuǎn)后的地址實(shí)例
這篇文章主要介紹了PHP使用CURL獲取302跳轉(zhuǎn)后的地址實(shí)例,需要的朋友可以參考下2014-05-05centos 7系統(tǒng)下安裝laravel運(yùn)行環(huán)境的步驟詳解
Laravel框架對(duì)于開發(fā)網(wǎng)頁應(yīng)用來說是一個(gè)絕好的的工具,最近正好又在學(xué)習(xí)linux系統(tǒng),所以下面這篇文章主要給大家介紹了在centos 7系統(tǒng)下安裝laravel運(yùn)行環(huán)境的步驟,需要的朋友可以參考借鑒,下面跟著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-08-08php使用curl檢測(cè)網(wǎng)頁是否被百度收錄的示例分享
這篇文章主要介紹了php使用curl檢測(cè)網(wǎng)頁是否被百度收錄的示例,需要的朋友可以參考下2014-01-01