引言
上一章内容我們介紹了使用laravel路由動詞定義友善的url,以及通過url參數綁定傳遞資料,
本文我們繼續深入Route功能,學習一些提升生産力的方法,在現實場景中也非常實用。

“昵稱”
如果你的應用程式路由條目可以達到300到500條,光是管理這些路由位址不重複,或者是浏覽某些部分的路由,
都将是一件非常考驗腦力的事兒。
有沒有想過,能不能給路由起個名字,友善記憶,不用想着路由定義的多複雜,咱們直接用别名通路?laravel為我們考慮到了,
比如路由這樣寫:
Route::get('members/{id}', 'MembersController@show')->name('members.show');
這樣定義之後在HTML檔案内比如有 a 标簽,或者 form 表單的 action,填url位址的時候,就可以使用laravel的助手函數,這樣來寫:
<a href="<?php echo route('members.show', ['id' => 14]); ?>">
這樣使用起來,就好像記一個函數名一樣,然後通過數組傳入綁定的位置參數,一般不容易寫錯,格式化也更好。比如我們之前講述的,使用laravel的 Route::resource() 方法生成 restful 風格的api,那麼如果對一個 Phone 模型相關的接口做别名,大概會是這樣子的:
photos.index
photos.create
photos.store
photos.show
photos.edit
photos.update
photos.destroy
其實助手函數 route 提供的參數傳入,可以靈活組裝url,比如按照位置傳入的資料,不指定鍵名,按順序傳入:
route('users.comments.show', [1, 2])
// http://myapp.com/users/1/comments/2
也可以明确鍵名,指定傳入的位置參數:
route('users.comments.show', ['userId' => 1, 'commentId' => 2])
// http://myapp.com/users/1/comments/2
為了驗證位置參數是否和數組鍵名綁定關系,我們颠倒傳入的參數順序,看看輸出是否如預期:
route('users.comments.show', ['commentId' => 2, 'userId' => 1])
// http://myapp.com/users/1/comments/2
可見,route函數是按照鍵名綁定到位置參數的。如果傳入的數組比可接受的資料要多,route函數會将其作為 get 方法的 querystring 進行傳遞:
route('users.comments.show', ['userId' => 1, 'commentId' => 2, 'opt' => 'a'])
// http://myapp.com/users/1/comments/2?opt=a
分組
分而治之,對于有相同類目的路由,應該歸類到一起,成為一個組。這就是路由組的由來。我們來看一下,不附加任何額外的功能的組是如何聲明的:
Route::group([], function () {
Route::get('hello', function () {
return 'Hello';
});
Route::get('world', function () {
return 'World';
});
});
有了分組,那麼可以手動指定,這個分組内所有注冊的路由,都要經過某個中間件,可以聲明如下:
Route::group(['middleware' => 'auth'], function () {
Route::get('dashboard', function () {
return view('dashboard');
});
Route::get('account', function () {
return view('account');
});
});
其中這個 'middleware' => 'auth' 的 auth 中間件,是聲明在 app/Http/Kernel.php 檔案内,下面這一段是源碼内自帶的中間件:
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];
我們可以直接拿來用。當然了,上面的示例是在路由組内引入的中間件。對于極為特殊的中間件功能,不能在路由組内統一引用的,可以放到控制器的構造函數内調用。比如下面的代碼:
class DashboardController extends Controller
{
public function __construct()
{
$this->middleware('auth');
$this->middleware('admin-auth')->only('admin');
$this->middleware('team-member')->except('admin');
}
}
因為控制器類已經繼承了中間件的注冊流程,是以可以有效使用中間件的攔截、驗證功能。
加字首
在規劃路由時,能省則省,功能一緻的放在一起,同時在路由數量多了之後,能夠有效地使用字首區分不同的功能子產品,也是一個很好的實踐。
為一組路由加字首,就想注冊中間件一樣,在配置内手動指定,比如下面這樣:
Route::group(['prefix' => 'api'], function () {
Route::get('/', function () {
// 路徑 /api
});
Route::get('users', function () {
// 路徑 /api/users
});
});
字首是給url路徑中路由部分指定的,我們還可以為二級域名指定路由,相似地,聲明如下代碼:
Route::group(['domain' => 'api.myapp.com'], function () {
Route::get('/', function () {
//
});
});
那麼該路由組内所有路由,就僅對指定的二級域名起作用。當然了二級域名還要使用nginx的反向代理配合使用。
laravel的花樣是真多啊!
不僅如此,我們還可以為路由組聲明是指定的命名空間下的控制器所使用的。這樣,可以通過把相似功能子產品放在相同命名空間下,進而達到路由分組的目的。比如:
Route::group(['namespace' => 'API'], function () {
// 對應 App\Http\Controllers\API\EventController
Route::get('api/', 'EventController@index');
});
寫在最後
laravel是給web藝術家準備的,你想到的,想不到的,基礎的,進階的功能都有了。沒有的,你也可以手動實作輪子夢。從上面注冊的路由方法,大家應該能有所感觸。
Happy coding :-)
我是 @程式員小助手 ,專注程式設計知識,圈子動态的IT領域原創作者