想象一下一個擁有 100 多個路由的 laravel 項目,其中包括訪客,用戶,管理員等分離的模塊。你真的要將所有內(nèi)容寫在在一個文件中嗎?那么如何將它們分組,并且為 url 添加前綴呢?看看有哪些辦法
1. 分離 WEB 和 API 路由
這個簡單,因為 Laravel 已經(jīng)幫你做了。有如下兩個文件:
routes/web.php
routes/api.php
因此,如果你的項目同時具有前端頁面和 API (使用場景越來越廣),請把 API 的路由放在 api.php 里。
例如,如果你有 /users 頁面,又有 /api/users/ 端點,把他們分別寫在自己屬于自己路由文件里,以免在同一文件中出現(xiàn)同一相同名稱而產(chǎn)生混淆。
但我最近還是從 官方 Laravel 項目中看到了反例。在 Laravel Horizon 中,Taylor 只有 API 路由,但他沒有分開寫,還是寫在了 routes/web.php :
另一個例子證明 Laravel 還是非常的個人化,甚至 Taylor 自己也沒有 100% 按照標準來。
2. 把 routes/web.php 文件分組結構化
下面例子也是來自 Laravel 官方文檔 的示例:
Route::middleware(['first',?'second'])->group(function?()?{ ????Route::get('/',?function?()?{ ????????//?使用?first?和?second?中間件 ????}); ????Route::get('user/profile',?function?()?{ ????????//?使用?first?和?second?中間件 ????}); });
最基本的用法是將不同的路由分組包含在不同的中間件里面。例如,你希望一個組默認受 auth 中間件限制,另一組受單獨的 admin 自定義中間件限制等。
這樣,你還可以使用 名稱 和 前綴 等路由分組方法。同樣,官方文檔中給出了示例:
Route::prefix('admin')->group(function?()?{ ????Route::get('users',?function?()?{ ????????//?匹配?URL?「/admin/users」 ????}); }); Route::name('admin.')->group(function?()?{ ????Route::get('users',?function?()?{ ????????//?路由名為?「admin.users」... ????})->name('users'); });
另外,如果您要將所有中間件 + 名稱 + 前綴添加到一個組中,則將它們放入數(shù)組中更容易理解:
//?而不是這樣做:? Route::name('admin.')->prefix('admin')->middleware('admin')->group(function?()?{ ????//?... }); //?可以使用數(shù)組 Route::group([ ????'name'?=>?'admin.',? ????'prefix'?=>?'admin',? ????'middleware'?=>?'auth' ],?function?()?{ ????//?... });
我們將其結合為一個擁有三個路由分組的真實示例:
帶有 / front / XXXXX URL 且沒有中間件的「訪客」組
帶有 / user / XXXXX URL 和 auth 中間件的「用戶」組
帶有 / admin / XXXXX URL 和自定義 admin 中間件的「管理員」組
以下是將所有內(nèi)容分組到 routes / web.php 文件中的一種方法:
Route::group([ ????'name'?=>?'admin.', ????'prefix'?=>?'admin', ????'middleware'?=>?'admin' ],?function?()?{ ????//?URL鏈接:/admin/users ????//?路由名稱:admin.users ????Route::get('users',?function?()?{ ????????return?'Admin:?user?list'; ????})->name('users'); }); Route::group([ ????'name'?=>?'user.', ????'prefix'?=>?'user', ????'middleware'?=>?'auth' ],?function?()?{ ????//?URL鏈接:/user/profile ????//?路由名稱:user.profile ????Route::get('profile',?function?()?{ ????????return?'User?profile'; ????})->name('profile'); }); Route::group([ ????'name'?=>?'front.', ????'prefix'?=>?'front' ],?function?()?{ ????//?這里沒有中間件 ????//?URL鏈接:/front/about-us ????//?路由名稱:front.about ????Route::get('about-us',?function?()?{ ????????return?'About?us?page'; ????})->name('about'); });
3. 使用命名空間對控制器進行分組
在上面的例子中,我們沒有使用控制器,只是返回了靜態(tài)文本作為示例。 讓我們添加一個控制器,來點小花樣 — 我們會將它們構造到各自不同的命名空間的文件夾中,如下所示:
然后我們可以在路由文件中使用它們:
Route::group([ ????'name'?=>?'front.', ????'prefix'?=>?'front' ],?function?()?{ ????Route::get('about-us',?'Front.boutController@index')->name('about'); });
但是如果在這個組中我們有很多控制器呢?我們應該一直添加 Front.omeController 嗎? 當然不是。您也可以將命名空間作為參數(shù)之一。
Route::group([ ????'name'?=>?'front.', ????'prefix'?=>?'front', ????'Namespace'?=>?'Front', ],?function?()?{ ????Route::get('about-us',?'AboutController@index')->name('about'); ????Route::get('contact',?'ContactController@index')->name('contact'); });
4. 組嵌套組
上面的情況,分為了 3 個組,實際上這是被簡化的, 實際項目的結構稍有不同 – 是 兩 個組:front 和 auth 。 然后在 auth 中,有兩個子組:user 和 admin 。為此, 我們可以在 routes/web.php 中創(chuàng)建子組,并分配不同的中間件 / 前綴等。
Route::group([ ????'middleware'?=>?'auth', ],?function()?{ ????Route::group([ ????????'name'?=>?'admin.', ????????'prefix'?=>?'admin', ????????'middleware'?=>?'admin' ????],?function?()?{ ????????//?URL:?/admin/users ????????//?Route?name:?admin.users ????????Route::get('users',?'UserController@index')->name('users'); ????}); ????Route::group([ ????????'name'?=>?'user.', ????????'prefix'?=>?'user', ????],?function?()?{ ????????//?URL:?/user/profile ????????//?Route?name:?user.profile ????????Route::get('profile',?'ProfileController@index')->name('profile'); ????}); });
我們甚至可以多層嵌套,這是開源項目的一個示例。 Akaunting:
Route::group(['middleware'?=>?'language'],?function?()?{ ????Route::group(['middleware'?=>?'auth'],?function?()?{ ????????Route::group(['prefix'?=>?'uploads'],?function?()?{ ????????????Route::get('{id}',?'Common.ploads@get'); ????????????Route::get('{id}/show',?'Common.ploads@show'); ????????????Route::get('{id}/download',?'Common.ploads@download'); ????????}); ????????Route::group(['middleware'?=>?'permission:read-admin-panel'],?function?()?{ ????????????Route::group(['prefix'?=>?'wizard'],?function?()?{ ????????????????Route::get('/',?'Wizard.ompanies@edit')->name('wizard.index'); ????????//?...
另一個例子來自另一個流行的 Laravel CRM,名為 Monica:
Route::middleware(['auth',?'verified',?'mfa'])->group(function?()?{ ????Route::name('dashboard.')->group(function?()?{ ????????Route::get('/dashboard',?'DashboardController@index')->name('index'); ????????Route::get('/dashboard/calls',?'DashboardController@calls'); ????????Route::get('/dashboard/notes',?'DashboardController@notes'); ????????Route::get('/dashboard/debts',?'DashboardController@debts'); ????????Route::get('/dashboard/tasks',?'DashboardController@tasks'); ????????Route::post('/dashboard/setTab',?'DashboardController@setTab'); ????});
5. RouteServiceProvider 中的全局設置
有一個服務于所有路由設置的文件 – app/Providers/RouteServiceProvider.php. 它具有綁定兩個路由文件 – web 和 API 的 map() 方法:
????public?function?map() ????{ ????????$this->mapApiRoutes(); ????????$this->mapWebRoutes(); ????} ????protected?function?mapWebRoutes() ????{ ????????Route::middleware('web') ?????????????->namespace($this->namespace) ?????????????->group(base_path('routes/web.php')); ????} ????protected?function?mapApiRoutes() ????{ ????????Route::prefix('api') ?????????????->middleware('api') ?????????????->namespace($this->namespace) ?????????????->group(base_path('routes/api.php')); ????}
您是否注意到方法中提及的 middleware, namespace 和 prefix ? 這是您可以為整個文件設置全局配置的地方,因此不必為文件中的每個路由組重復這些設置。
它主要用于 API 路由,因為它們的設置通常是相同的,如下所示:
protected?function?mapApiRoutes() { ????Route::group([ ????????'middleware'?=>?['api'], ????????'namespace'?=>?$this->namespace, ????????'prefix'?=>?'api/v1', ????],?function?($router)?{ ????????require?base_path('routes/api.php'); ????}); }
上述方法將在所有 API URLs 的開頭加上 api/v1/ 前綴。
6. 分組成更多文件 – 這值得嗎?
如果您有大量的路由,并且希望將它們分組到單獨的文件中,那么您可以使用上一節(jié)中提到的相同文件 – app/Providers/RouteServiceProvider.php。如果您仔細查看它的 map() 方法,您將在末尾看到注釋位置:
public?function?map() { ????$this->mapApiRoutes(); ????$this->mapWebRoutes(); ????// }
如果愿意,您可以將其解釋為添加更多文件的 “邀請”。因此,您可以在此文件內(nèi)創(chuàng)建另一個方法,例如 mapAdminRoutes(),然后將其添加到 map() 方法, 您的文件將被自動注冊并加載。
但是,就我個人而言,我看不出這種方法有什么優(yōu)勢,而且我也沒有經(jīng)常看到這種做法。它會帶來更多的路由分離,但有時您會迷失在那些文件中,不確定在哪里查找特定的路由。
7. 使用 Artisan route:list 命令查找特定路由
說到更大的路由并迷失在那里,我們有一個 Artisan 命令可以幫助定位某個路由。
您可能知道 php artisan route:list 將展示項目中的所有路由
但您知道還有更多的過濾功能來找到您想要的東西嗎? 只需添加帶參數(shù)的 –method, 或 –name, 或 –path 。
通過 method 過濾 – GET, POST 等:
按名稱或 URL 部分過濾:
推薦教程:《laravel》