## router.php
1、基本路由
所有應用路由都定義在 App\Providers\RouteServiceProvider 類載入的 app/Http/routes.php 文件中。
最基本的 Laravel 路由接收一個 URI 和一個閉包:
Route::get('foo', function () {
return 'Hello World';
});
Route::post('foo', function () {
//
});
默認情況下,routes.php 文件包含單個路由和一個路由群組,該路由群組包含的所有路由都使用了中間件組 web,而這個中間件組為路由提供了 Session 狀態和 CSRF 保護功能。通常,我們會將所有路由定義在這個路由組中。
有效的路由方法
我們可以注冊路由來響應任何 HTTP 請求:
Route::get($uri, $callback);
Route::post($uri, $callback);
Route::put($uri, $callback);
Route::patch($uri, $callback);
Route::delete($uri, $callback);
Route::options($uri, $callback);
有時候還需要注冊路由響應多個 HTTP 請求——這可以通過 match 方法來實現。或者,甚至可以使用 any 方法注冊一個路由來響應所有 HTTP 請求:
Route::match(['get', 'post'], '/', function () {
//
});
Route::any('foo', function () {
//
});
2、路由參數
必選參數
有時我們需要在路由中捕獲 URI 片段。比如,要從 URL 中捕獲用戶 ID,需要通過如下方式定義路由參數:
Route::get('user/{id}', function ($id) {
return 'User '.$id;
});
可以按需要在路由中定義多個路由參數:
Route::get('posts/{post}/comments/{comment}', function ($postId, $commentId) {
//
});
路由參數總是通過花括號進行包裹,這些參數在路由被執行時會被傳遞到路由的閉包。
注意:路由參數不能包含 - 字符,需要的話可以使用 _ 替代。
可選參數
有時候可能需要指定可選的路由參數,這可以通過在參數名后加一個 ? 標記來實現,這種情況下需要給相應的變量指定默認值:
Route::get('user/{name?}', function ($name = null) {
return $name;
});
Route::get('user/{name?}', function ($name = 'John') {
return $name;
});
正則約束
可以使用路由實例上的where方法來約束路由參數的格式。where方法接收參數名和一個正則表達式來定義該參數如何被約束:
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]+']);
全局約束
如果想要路由參數在全局范圍內被給定正則表達式約束,可以使用pattern方法。在RouteServiceProvider類的boot方法中定義約束模式:
/**
* 定義路由模型綁定,模式過濾器等
*
* @param \Illuminate\Routing\Router $router
* @return void
*
*/
public function boot(Router $router){
$router->pattern('id', '[0-9]+');
parent::boot($router);
}
一旦模式被定義,將會自動應用到所有包含該參數名的路由中:
Route::get('user/{id}', function ($id) {
// 只有當 {id} 是數字時才會被調用
});
3、命名路由
命名路由為生成 URL 或重定向提供了便利。實現也很簡單,在定義路由時使用數組鍵 as 指定路由名稱:
Route::get('user/profile', ['as' => 'profile', function () {
//
}]);
此外,還可以為控制器動作指定路由名稱:
Route::get('user/profile', [
'as' => 'profile', 'uses' => 'UserController@showProfile'
]);
此外,除了在路由數組定義中指定路由名稱外,還可以通過在路由定義之后使用 name 方法鏈的方式來實現:
Route::get('user/profile', 'UserController@showProfile')->name('profile');
路由群組 & 命名路由
如果你在使用路由群組,可以通過在路由群組的屬性數組中指定 as 關鍵字來為群組中的路由設置一個共用的路由名前綴:
Route::group(['as' => 'admin::'], function () {
Route::get('dashboard', ['as' => 'dashboard', function () {
// 路由被命名為 "admin::dashboard"
}]);
});
為命名路由生成URL
如果你為給定路由進行了命名,就可以通過 route 函數為該命名路由生成對應 URL:
$url = route('profile');
$redirect = redirect()->route('profile');
如果命名路由定義了參數,可以將該參數作為第二個參數傳遞給 route 函數。給定的路由參數將會自動插入 URL 中:
Route::get('user/{id}/profile', ['as' => 'profile', function ($id) {
//
}]);
$url = route('profile', ['id' => 1]);
4、路由群組
路由群組允許我們在多個路由中共享路由屬性,比如中間件和命名空間等,這樣的話我們就不必為每一個路由單獨定義屬性。共享屬性以數組的形式作為第一個參數被傳遞給 Route::group 方法。
下面我們通過幾個簡單的應用實例來演示路由群組。
中間件
要給路由群組中定義的所有路由分配中間件,可以在群組屬性數組中使用 middleware。中間件將會按照數組中定義的順序依次執行:
Route::group(['middleware' => 'auth'], function () {
Route::get('/', function () {
// 使用 Auth 中間件
});
Route::get('user/profile', function () {
// 使用 Auth 中間件
});
});
命名空間
另一個通用的例子是路由群組分配同一個 PHP 命名空間給其下的多個控制器,可以在分組屬性數組中使用 namespace 來指定群組中所有控制器的公共命名空間:
Route::group(['namespace' => 'Admin'], function(){
// 控制器在 "App\Http\Controllers\Admin" 命名空間下
Route::group(['namespace' => 'User'], function(){
// 控制器在 "App\Http\Controllers\Admin\User" 命名空間下
});
});
默認情況下,RouteServiceProvider 引入 routes.php 并指定其下所有控制器類所在的默認命名空間 App\Http\Controllers,因此,我們在定義的時候只需要指定命名空間 App\Http\Controllers 之后的部分即可。
子域名路由
路由群組還可以被用于子域名路由通配符,子域名可以像 URI 一樣被分配給路由參數,從而允許捕獲子域名的部分用于路由或者控制器,子域名可以通過群組屬性數組中的 domain 來指定:
Route::group(['domain' => '{account}.myapp.com'], function () {
Route::get('user/{id}', function ($account, $id) {
//
});
});
路由前綴
群組屬性 prefix 可以用來為群組中每個路由添加一個給定 URI 前綴,比如,你可以為所有路由 URI 添加 admin 前綴 :
Route::group(['prefix' => 'admin'], function () {
Route::get('users', function () {
// 匹配 "/admin/users" URL
});
});
你還可以使用 prefix 參數為路由群組指定公共路由參數:
Route::group(['prefix' => 'accounts/{account_id}'], function () {
Route::get('detail', function ($account_id) {
// 匹配 accounts/{account_id}/detail URL
});
});