Laravel Http 層---路由

1、基本路由

最基本的 Laravel 路由只接收一個(gè) URI 和一個(gè)閉包罕拂,并以此提供一個(gè)非常簡(jiǎn)單且優(yōu)雅的定義路由方法:

Route::get('foo', function () {
    return 'Hello World';
});

默認(rèn)路由文件
有 Laravel 路由都定義在位于 routes 目錄下的路由文件中埋合,這些文件通過(guò)框架自動(dòng)加載备徐。
routes/web.php 文件定義了web界面的路由,這些路由被分配了web
中間件組甚颂,從而可以提供session和csrf防護(hù)等功能蜜猾。
routes/api.php 中的路由是無(wú)狀態(tài)的,被分配了 api
中間件組西设。

對(duì)大多數(shù)應(yīng)用而言瓣铣,都是從 routes/web.php 文件開始定義路由。

我們可以注冊(cè)路由來(lái)響應(yīng)任何 HTTP 請(qǐng)求:

//get 請(qǐng)求
Route::get($uri, $callback);
//post 請(qǐng)求
Route::post($uri, $callback);
//put 請(qǐng)求
Route::put($uri, $callback);
//patch 請(qǐng)求
Route::patch($uri, $callback);
//delete 請(qǐng)求
Route::delete($uri, $callback);
//options 請(qǐng)求
Route::options($uri, $callback);

有時(shí)候還需要注冊(cè)路由響應(yīng)多個(gè) HTTP 請(qǐng)求——這可以通過(guò) match 方法來(lái)實(shí)現(xiàn)贷揽√男Γ或者,可以使用 any 方法注冊(cè)一個(gè)路由來(lái)響應(yīng)所有 HTTP 請(qǐng)求:

Route::match(['get', 'post'], '/', function () {
    //
});

Route::any('foo', function () {
    //
});

CSRF防護(hù)
在 web
路由文件中所有請(qǐng)求方式為PUT禽绪、POSTDELETE 的HTML表單都會(huì)包含一個(gè)CSRF令牌字段蓖救,否則,請(qǐng)求會(huì)被拒絕印屁。關(guān)于CSRF的更多細(xì)節(jié)循捺,可以參考CSRF文檔

<form method="POST" action="/profile">
   {{ csrf_field() }}
   ...
</form>

2、路由參數(shù)

必選參數(shù)
有時(shí)我們需要在路由中捕獲 URI 片段雄人。比如从橘,要從 URL 中捕獲用戶ID念赶,需要通過(guò)如下方式定義路由參數(shù):

Route::get('user/{id}', function ($id) {
    return 'User '.$id;
});

可以按需要在路由中定義多個(gè)路由參數(shù):

Route::get('/hello/{name}/by/{user}',function($name,$user){
    return "Hello {$name} by {$user}!";
});

路由參數(shù)總是通過(guò){}進(jìn)行包裹,這些參數(shù)在路由被執(zhí)行時(shí)會(huì)被傳遞到路由的閉包恰力。路由參數(shù)不能包含 - 字符叉谜,需要的話可以使用 _ 替代。

注意以上參數(shù)是必選的踩萎,如果沒(méi)有輸入?yún)?shù)會(huì)拋出 MethodNotAllowedHttpExceptionNotFoundHttpException 異常停局。

此外閉包函數(shù)中的參數(shù)與路由參數(shù)一一對(duì)應(yīng)。

可選參數(shù)
有時(shí)候可能需要指定可選的路由參數(shù)香府,這可以通過(guò)在參數(shù)名后加一個(gè) ? 標(biāo)記來(lái)實(shí)現(xiàn)董栽,這種情況下需要給相應(yīng)的變量指定默認(rèn)值:

Route::get('user/{name?}', function ($name = null) {
    return $name;
});
Route::get('user/{name?}', function ($name = 'John') {
    return $name;
});

正則約束
可以使用路由實(shí)例上的 where 方法來(lái)約束路由參數(shù)的格式。where 方法接收參數(shù)名為鍵和一個(gè)正則表達(dá)式為值的數(shù)組來(lái)定義該參數(shù)如何被約束:

Route::get('user/{name}', function ($name) {
    //
})->where('name', '[A-Za-z]+');

Route::get('user/{id}', function ($id) {
    //
})->where('id', '[0-9]+');

Route::get('user/{id}/{name}', function ($id, $name) {
    //
})->where(['id' => '[0-9]+', 'name' => '[a-z]+']);

全局約束
如果想要路由參數(shù)在全局范圍內(nèi)被給定正則表達(dá)式約束企孩,可以使用 pattern 方法锭碳。在RouteServiceProvider 類的 boot 方法中定義約束模式:

/**
 * 定義路由模型綁定,模式過(guò)濾器等
 * 
* @param \Illuminate\Routing\Router $router 
* @return void 
* @translator 
*/
public function boot(){
 Route::pattern('id', '[0-9]+');
 parent::boot();
}

一旦模式被定義,將會(huì)自動(dòng)應(yīng)用到所有包含該參數(shù)名的路由中:

Route::get('user/{id}', function ($id) {
    // 只有當(dāng) {id} 是數(shù)字時(shí)才會(huì)被調(diào)用
});

3勿璃、命名路由

命名路由為生成 URL重定向提供了便利工禾。實(shí)現(xiàn)也很簡(jiǎn)單,在路由定義之后使用 name 方法鏈的方式來(lái)實(shí)現(xiàn):

Route::get('user/profile', function () {
    //
})->name('profile');

還可以為控制器動(dòng)作指定路由名稱:

Route::get('user/profile', 'UserController@showProfile')->name('profile');

為命名路由生成URL重定向
給定路由分配名稱之后蝗柔,就可以通過(guò)輔助函數(shù) route 為該命名路由生成 URL:

$url = route('profile');
return redirect()->route('profile');

如果命名路由定義了參數(shù),可以將該參數(shù)作為第二個(gè)參數(shù)傳遞給 route 函數(shù)民泵。給定的路由參數(shù)將會(huì)自動(dòng)插入到 URL 中:

Route::get('user/{id}/profile', function ($id) {
    //
})->name('profile');

$url = route('profile', ['id' => 1]);

4癣丧、路由群組

路由分組就是將一組擁有相同屬性(中間件命名空間栈妆、子域名胁编、路由前綴等)的路由使用 Route Facadegroup 方法聚合起來(lái)。

共享屬性以數(shù)組的形式作為第一個(gè)參數(shù)被傳遞給 Route::group 方法鳞尔。

中間件

要給路由群組中定義的所有路由分配中間件嬉橙,可以在群組屬性數(shù)組中使用 middleware。中間件將會(huì)按照數(shù)組中定義的順序依次執(zhí)行:

Route::group(['middleware' => 'auth'], function () {
    Route::get('/', function () {
        // 使用 Auth 中間件
    });

    Route::get('user/profile', function () {
        // 使用 Auth 中間件
    });
});

命名空間

命名空間可以通過(guò)namespace關(guān)鍵字來(lái)設(shè)置寥假。

默認(rèn)情況下市框, RouteServiceProvider 引入你的路由文件并指定其下所有控制器類所在的默認(rèn)命名空間App\Http\Controllers,因此糕韧,我們?cè)诙x的時(shí)候只需要指定命名空間 App\Http\Controllers 之后的部分即可 :

Route::group(['namespace' => 'Admin'], function(){
    // 控制器在 "App\Http\Controllers\Admin" 命名空間下
});

子域名路由

子域名可以通過(guò)domain關(guān)鍵字來(lái)設(shè)置 :

Route::group(['domain' => '{account}.myapp.com'], function () {
    Route::get('user/{id}', function ($account, $id) {
        //
    });
});

這樣我們?cè)跒g覽器中訪問(wèn)http://xiao.myapp.com/user/5枫振。

路由前綴

路由前綴可以通過(guò) prefix 關(guān)鍵字來(lái)設(shè)置 :

Route::group(['prefix' => 'admin'], function () {
    Route::get('users', function () {
        // 匹配 "/admin/users" URL
    });
});

5、路由模型綁定

注入模型ID到路由或控制器動(dòng)作時(shí)萤彩,通常需要查詢數(shù)據(jù)庫(kù)才能獲取相應(yīng)的模型數(shù)據(jù)粪滤。Laravel 路由模型綁定讓注入模型實(shí)例到路由變得簡(jiǎn)單,例如雀扶,你可以將匹配給定 ID 的整個(gè) User 類實(shí)例注入到路由中杖小,而不是直接注入用戶ID。

隱式綁定

Laravel 會(huì)自動(dòng)解析定義在路由或控制器動(dòng)作(變量名匹配路由片段)中的 Eloquent 模型類型聲明,例如:

Route::get('api/users/{user}', function (App\User $user) {
    return $user->email;
});

在這個(gè)例子中予权,由于類型聲明了 Eloquent 模型 App\User昂勉,對(duì)應(yīng)的變量名 $user 會(huì)匹配路由片段中的 {user},這樣伟件,Laravel 會(huì)自動(dòng)注入與請(qǐng)求 URI 中傳入的 ID 對(duì)應(yīng)的用戶模型實(shí)例硼啤。

如果數(shù)據(jù)庫(kù)中找不到對(duì)應(yīng)的模型實(shí)例,會(huì)自動(dòng)生成 HTTP 404 響應(yīng)斧账。

自定義鍵名
如果你想要在隱式模型綁定中使用數(shù)據(jù)表的其它字段谴返,可以重寫 Eloquent 模型類的 getRouteKeyName 方法:

/**
 * 獲取模型的路由密鑰.
 *
 * @return string
 */
public function getRouteKeyName()
{
    return 'slug';
}

顯式綁定

要注冊(cè)顯式綁定,需要使用路由的 model 方法來(lái)為給定參數(shù)指定綁定類咧织。應(yīng)該在 RouteServiceProvider 類的 boot 方法中定義模型綁定:

public function boot()
{
    parent::boot();
    Route::model('user', App\User::class);
}

接下來(lái)嗓袱,定義一個(gè)包含 {user} 參數(shù)的路由:

$router->get('profile/{user}', function(App\User $user) {
     //
});

由于我們已經(jīng)綁定 {user} 參數(shù)到 App\User 模型,User 實(shí)例會(huì)被注入到該路由习绢。因此渠抹,如果請(qǐng)求 URL 是 profile/1,就會(huì)注入一個(gè)用戶 ID 為 1User 實(shí)例闪萄。

如果匹配的模型實(shí)例在數(shù)據(jù)庫(kù)不存在梧却,會(huì)自動(dòng)生成并返回 HTTP 404 響應(yīng)。

自定義解析邏輯

如果你想要使用自定義的解析邏輯败去,需要使用 Route::bind 方法放航,傳遞到 bind 方法的閉包會(huì)獲取到 URI 請(qǐng)求參數(shù)中的值,并且返回你想要在該路由中注入的類實(shí)例:

public function boot()
{
    parent::boot();

    Route::bind('user', function($value) {
        return App\User::where('name', $value)->first();
    });
}

6圆裕、表單方法偽造

HTML 表單不支持 PUT广鳍、PATCH 或者 DELETE 請(qǐng)求方法,因此吓妆,當(dāng)定義 PUT赊时、PATCHDELETE 路由時(shí),需要添加一個(gè)隱藏的 _method 字段到表單中行拢,其值被用作該表單的 HTTP 請(qǐng)求方法:

<form action="/foo/bar" method="POST">
    <input type="hidden" name="_method" value="PUT">
    <input type="hidden" name="_token" value="{{ csrf_token() }}">
</form>

還可以使用輔助函數(shù) method_field 來(lái)實(shí)現(xiàn)這一目的:

{{ method_field('PUT') }}

7祖秒、訪問(wèn)當(dāng)前路由

你可以使用 Route Facade 上的 currentcurrentRouteNamecurrentRouteAction 方法來(lái)訪問(wèn)處理當(dāng)前輸入請(qǐng)求的路由信息:

$route = Route::current();
$name = Route::currentRouteName();
$action = Route::currentRouteAction();

參考API文檔了解路由門面底層類以及Route實(shí)例的更多可用方法舟奠。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末狈涮,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子鸭栖,更是在濱河造成了極大的恐慌歌馍,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件晕鹊,死亡現(xiàn)場(chǎng)離奇詭異松却,居然都是意外死亡暴浦,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門晓锻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)歌焦,“玉大人,你說(shuō)我怎么就攤上這事砚哆《榔玻” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵躁锁,是天一觀的道長(zhǎng)纷铣。 經(jīng)常有香客問(wèn)我,道長(zhǎng)战转,這世上最難降的妖魔是什么搜立? 我笑而不...
    開封第一講書人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮槐秧,結(jié)果婚禮上啄踊,老公的妹妹穿的比我還像新娘。我一直安慰自己刁标,他們只是感情好颠通,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著膀懈,像睡著了一般蒜哀。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上吏砂,一...
    開封第一講書人閱讀 51,679評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音乘客,去河邊找鬼狐血。 笑死,一個(gè)胖子當(dāng)著我的面吹牛易核,可吹牛的內(nèi)容都是我干的匈织。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼牡直,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼缀匕!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起碰逸,我...
    開封第一講書人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤乡小,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后饵史,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體满钟,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡胜榔,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了湃番。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片夭织。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖吠撮,靈堂內(nèi)的尸體忽然破棺而出尊惰,到底是詐尸還是另有隱情,我是刑警寧澤泥兰,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布弄屡,位于F島的核電站,受9級(jí)特大地震影響逾条,放射性物質(zhì)發(fā)生泄漏琢岩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一师脂、第九天 我趴在偏房一處隱蔽的房頂上張望担孔。 院中可真熱鬧,春花似錦吃警、人聲如沸糕篇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)拌消。三九已至,卻和暖如春安券,著一層夾襖步出監(jiān)牢的瞬間墩崩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工侯勉, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鹦筹,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓址貌,卻偏偏與公主長(zhǎng)得像铐拐,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子练对,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容