掌握Laravel路由

掌握Laravel路由

當涉及到後端時,開發人員最終會遇到路由。路由可以被認為是後臺的骨幹,因為伺服器收到的每個請求都會通過路由列表重定向到一個控制器,將請求對映到控制器或動作。

Laravel為我們隱藏了許多實現細節,並配有大量的語法糖,以幫助新的和有經驗的開發人員開發他們的Web應用程式。

  1. 後臺路由和跨站指令碼在Laravel中的應用
  2. Laravel基本路由
  3. 路由引數
  4. 命名的路由
  5. 路由組
  6. 路由快取

後臺路由和跨站指令碼在Laravel中的應用

在一個伺服器上,存在著公共和私人路由。由於跨網站指令碼(XSS)的可能性,公共路由可能是一個令人擔憂的問題,這種型別的注入攻擊可能使你和你的使用者容易受到惡意行為者的攻擊

問題是,使用者可以從一個不需要會話令牌的路由重定向到一個需要會話令牌的路由–而且他們仍然可以在沒有令牌的情況下訪問。

解決這個問題的最簡單方法是執行一個新的HTTP頭,在路由中加入 “referrer”,以緩解這種情況:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
'main' => [
'path' => '/main',
'referrer' => 'required,refresh-empty',
'target' => Controller\DashboardController::class . '::mainAction'
]
'main' => [ 'path' => '/main', 'referrer' => 'required,refresh-empty', 'target' => Controller\DashboardController::class . '::mainAction' ]
'main' => [
'path' => '/main',
'referrer' => 'required,refresh-empty',
'target' => Controller\DashboardController::class . '::mainAction'
]

Laravel基本路由

在Laravel中, 路由允許使用者將適當的請求路由到所需的控制器。最基本的Laravel路由接受一個統一的資產識別符號(你的路由路徑)和一個閉包,可以是一個函式或一個類。

在Laravel中, 路由是在web.phpapi.php檔案中建立的. Laravel預設有兩個路由: 一個用於WEB, 一個用於API.

這些路由位於routes/資料夾中, 但它們是在Providers/RouteServiceProvider.php中載入的。

Laravel的路由服務提供者的預設狀態

Laravel的路由服務提供者的預設狀態

與其這樣,我們可以直接在RouteServiceProvider.php中載入路由,完全跳過routes/資料夾。

直接在供應商中載入Laravel路由

直接在供應商中載入Laravel路由

重定向

當我們定義一個路由時,我們通常會想重定向訪問它的使用者,而這樣做的原因有很多。這可能是因為它是一個廢棄的路由,我們已經改變了後臺或伺服器,也可能是因為我們想安裝雙因素認證(2FA),等等。

Laravel有一個簡單的方法來做到這一點。由於該框架的簡單性, 我們可以使用Route facade上的重定向方法, 它接受入口路線和要重定向的路線.

另外,我們可以把重定向的狀態程式碼作為第三個引數。 permanentRedirect 方法的作用與 redirect 方法相同,只是它總是返回一個301狀態程式碼

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Simple redirect
Route::redirect("/class", "/myClass");
// Redirect with custom status
Route::redirect("/home", "/office", 305);
// Route redirect with 301 status code
Route::permanentRedirect("/home", "office");
// Simple redirect Route::redirect("/class", "/myClass"); // Redirect with custom status Route::redirect("/home", "/office", 305); // Route redirect with 301 status code Route::permanentRedirect("/home", "office");
// Simple redirect
Route::redirect("/class", "/myClass");
// Redirect with custom status
Route::redirect("/home", "/office", 305);
// Route redirect with 301 status code
Route::permanentRedirect("/home", "office");

在重定向路線中,我們禁止使用 “destination “和 “status “關鍵字作為引數,因為它們是Laravel保留的。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Illegal to use
Route::redirect("/home", "/office/{status}");
// Illegal to use Route::redirect("/home", "/office/{status}");
// Illegal to use
Route::redirect("/home", "/office/{status}");

檢視

檢視是 .blade.php 檔案,我們用它來渲染我們Laravel應用程式的前端。它使用了blade模板引擎, 它是隻使用Laravel構建全棧應用的預設方式。

如果我們想讓我們的路由返回一個檢視, 我們可以簡單地使用路由介面上的檢視方法。它接受一個路由引數,一個檢視名稱,和一個可選的值陣列來傳遞給檢視。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// When the user accesses my-domain.com/homepage
// the homepage.blade.php file will be rendered
Route::view("/homepage", "homepage");
// When the user accesses my-domain.com/homepage // the homepage.blade.php file will be rendered Route::view("/homepage", "homepage");
// When the user accesses my-domain.com/homepage
// the homepage.blade.php file will be rendered
Route::view("/homepage", "homepage");

讓我們假設我們的檢視想說“Hello, {name}”,通過傳遞一個帶有該引數的可選陣列。我們可以用下面的程式碼來實現這個目的(如果檢視中缺少的引數是必需的,那麼請求就會失敗並丟擲一個錯誤):

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Route::view('/homepage', 'homepage', ['name' => "Wbolt"]);
Route::view('/homepage', 'homepage', ['name' => "Wbolt"]);
Route::view('/homepage', 'homepage', ['name' => "Wbolt"]);

路由列表

隨著你的應用程式規模的增長,需要路由的請求的數量也會增加。而大量的資訊會帶來巨大的混亂。

這就是 artisan route:list command 可以幫助我們的地方。它提供了一個在應用程式中定義的所有路由、它們的中介軟體和控制器的概覽。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
php artisan route:list
php artisan route:list
php artisan route:list

它將顯示一個不含中介軟體的所有路由的列表。為此,我們必須使用 -v 標誌。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
php artisan route:list -v
php artisan route:list -v
php artisan route:list -v

在你可能使用域驅動設計的情況下,你的路由在其路徑中具有特定的名稱,你可以像這樣利用這個命令的過濾功能:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
php artisan route:list –path=api/account
php artisan route:list –path=api/account
php artisan route:list –path=api/account

這將只顯示以api/account開頭的路由。

另一方面, 我們可以通過使用 –except-vendor 或 –only-vendor 選項來指示Laravel排除或包括第三方定義的路由.

路由引數

有時你可能需要用路由來捕獲URI的片段,如使用者ID或令牌。我們可以通過定義一個路由引數來做到這一點, 這個引數總是被包裹在大括號裡 ({}) , 而且應該只由字母組成.

如果我們的路由在他們的回撥裡面有依賴性,Laravel服務容器會自動注入它們:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
use Illuminate\Http\Request;
use Controllers/DashboardController;
Route::post('/dashboard/{id}, function (Request $request, string $id) {
return 'User:' . $id;
}
Route::get('/dashboard/{id}, DashboardController.php);
use Illuminate\Http\Request; use Controllers/DashboardController; Route::post('/dashboard/{id}, function (Request $request, string $id) { return 'User:' . $id; } Route::get('/dashboard/{id}, DashboardController.php);
use Illuminate\Http\Request;
use Controllers/DashboardController;
Route::post('/dashboard/{id}, function (Request $request, string $id) {
return 'User:' . $id;
}
Route::get('/dashboard/{id}, DashboardController.php);

必要的引數

Laravel的必要引數是路由中的引數, 當我們進行呼叫時, 不允許跳過這些引數. 否則就會出現錯誤:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Route::post("/gdpr/{userId}", GetGdprDataController.php");
Route::post("/gdpr/{userId}", GetGdprDataController.php");
Route::post("/gdpr/{userId}", GetGdprDataController.php");

現在在GetGdprDataController.php中,我們將可以直接訪問$userId引數。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public function __invoke(int $userId) {
// Use the userId that we received…
}
public function __invoke(int $userId) { // Use the userId that we received… }
public function __invoke(int $userId) {
// Use the userId that we received…
}

一個路由可以接受任何數量的引數。它們被注入路由的回撥/控制器中,基於它們被列出的順序:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// api.php
Route::post('/gdpr/{userId}/{userName}/{userAge}', GetGdprDataController.php);
// GetGdprDataController.php
public function __invoke(int $userId, string $userName, int $userAge) {
// Use the parameters…
}
// api.php Route::post('/gdpr/{userId}/{userName}/{userAge}', GetGdprDataController.php); // GetGdprDataController.php public function __invoke(int $userId, string $userName, int $userAge) { // Use the parameters… }
 // api.php
Route::post('/gdpr/{userId}/{userName}/{userAge}', GetGdprDataController.php);
// GetGdprDataController.php
public function __invoke(int $userId, string $userName, int $userAge) {
// Use the parameters…
}

可選引數

在這樣的情況下,我們想在只有一個引數存在的情況下在路由上做一些事情,而不影響整個應用程式,我們可以新增一個可選引數。這些可選引數由附加在其上的 ? 表示:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Route::get('/user/{age?}', function (int $age = null) {
if (!$age) Log::info("User doesn't have age set");
else Log::info("User's age is " . $age);
}
Route::get('/user/{name?}', function (int $name = "John Doe") {
Log::info("User's name is " . $name);
}
Route::get('/user/{age?}', function (int $age = null) { if (!$age) Log::info("User doesn't have age set"); else Log::info("User's age is " . $age); } Route::get('/user/{name?}', function (int $name = "John Doe") { Log::info("User's name is " . $name); }
 Route::get('/user/{age?}', function (int $age = null) {
if (!$age) Log::info("User doesn't have age set");
else Log::info("User's age is " . $age);
}
Route::get('/user/{name?}', function (int $name = "John Doe") {
Log::info("User's name is " . $name);
}

路由萬用字元

Laravel為我們提供了一種方法來過濾我們的可選或必需引數應該是什麼樣子.

比如我們想要一個使用者ID的字串. 我們可以使用 where 方法在路由層面進行驗證。

where 方法接受引數的名稱和將被應用於驗證的regex規則。預設情況下,它接受第一個引數,但如果我們有很多引數,我們可以傳遞一個陣列,以引數名稱為鍵,以規則為值,Laravel將為我們解析所有引數:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Route::get('/user/{age}', function (int $age) {
//
}->where('age', '[0-9]+');
Route::get('/user/{age}', function (int $age) {
//
}->where('[0-9]+');
Route::get('/user/{age}/{name}', function (int $age, string $name) {
//
}->where(['age' => '[0-9]+', 'name' => '[a-z][A-z]+');
Route::get('/user/{age}', function (int $age) { // }->where('age', '[0-9]+'); Route::get('/user/{age}', function (int $age) { // }->where('[0-9]+'); Route::get('/user/{age}/{name}', function (int $age, string $name) { // }->where(['age' => '[0-9]+', 'name' => '[a-z][A-z]+');
Route::get('/user/{age}', function (int $age) {
//
}->where('age', '[0-9]+');
Route::get('/user/{age}', function (int $age) {
//
}->where('[0-9]+');
Route::get('/user/{age}/{name}', function (int $age, string $name) {
//
}->where(['age' => '[0-9]+', 'name' => '[a-z][A-z]+');

我們可以更進一步,通過使用 Route facade上的 pattern 方法對我們應用程式中的所有路由進行驗證。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Route::pattern('id', '[0-9]+');
Route::pattern('id', '[0-9]+');
 Route::pattern('id', '[0-9]+');

這將用這個regex表示式對每個 id 引數進行估值。一旦我們定義了它, 它就會自動應用於所有使用該引數名稱的路由。

我們可以看到, Laravel在路由中使用 / 字元作為分隔符. 如果我們想在路由中使用它,我們必須使用 where regex明確允許它成為我們佔位符的一部分。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Route::get('/find/{query}', function ($query) {
//
})->where('query', , '.*');
Route::get('/find/{query}', function ($query) { // })->where('query', , '.*');
 Route::get('/find/{query}', function ($query) {
//
})->where('query', , '.*');

唯一的缺點是,它只在最後一個路由段得到支援。

命名的路由

顧名思義,我們可以為路由命名,這使得我們可以方便地為特定的路由生成URL或重定向。

建立命名路由的一個簡單方法是由 Route  facade上的 name 方法鏈提供的。每個路由的名字都應該是唯一的:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Route::get('/', function () {
})->name("homepage");
Route::get('/', function () { })->name("homepage");
 Route::get('/', function () {
})->name("homepage");

路由組

路由組允許你在大量的路由中共享像中介軟體這樣的路由屬性,而不需要在每一個路由上重新定義。

中介軟體

為我們擁有的所有路由分配一箇中介軟體,允許我們將它們組合在一個組中,首先使用 group 方法。需要考慮的一點是,中介軟體是按照應用到組中的順序來執行的:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Route:middleware(['AuthMiddleware', 'SessionMiddleware'])->group(function () {
Route::get('/', function() {} );
Route::post('/upload-picture', function () {} );
});
Route:middleware(['AuthMiddleware', 'SessionMiddleware'])->group(function () { Route::get('/', function() {} ); Route::post('/upload-picture', function () {} ); });
 Route:middleware(['AuthMiddleware', 'SessionMiddleware'])->group(function () {
Route::get('/', function() {} );
Route::post('/upload-picture', function () {} );
});

控制器

當一個組使用同一個控制器時,我們可以使用 controller 方法來定義該組內所有路由的共同控制器。現在我們必須指定路由將呼叫的方法。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Route::controller(UserController::class)->group(function () {
Route::get('/orders/{userId}', 'getOrders');
Route::post('/order/{id}', 'postOrder');
});
Route::controller(UserController::class)->group(function () { Route::get('/orders/{userId}', 'getOrders'); Route::post('/order/{id}', 'postOrder'); });
 Route::controller(UserController::class)->group(function () {
Route::get('/orders/{userId}', 'getOrders');
Route::post('/order/{id}', 'postOrder');
});

子域路由

子域名稱是新增到網站域名開頭的一段額外資訊。這允許網站將其特定功能的內容分開並組織起來,如網上商店、部落格、簡報等與網站的其他部分分開。

我們的路由可以用來處理子域名的路由。我們可以抓住域和子域的一部分,在我們的控制器和路由中使用。在 Route facade上的 domain 方法的幫助下,我們可以將我們的路由放在一個單一的域下:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Route::domain('{store}.enterprise.com')->group(function() {
Route::get('order/{id}', function (Account $account, string $id) {
// Your Code
}
});
Route::domain('{store}.enterprise.com')->group(function() { Route::get('order/{id}', function (Account $account, string $id) { // Your Code } });
 Route::domain('{store}.enterprise.com')->group(function() {
Route::get('order/{id}', function (Account $account, string $id) {
// Your Code
}
});

字首和名稱字首

每當我們有一組路由時, 我們可以利用Laravel提供的額外工具, 例如 Route 介面上的 prefix 和 name , 而不是一個一個的修改它們.

prefix 方法可以用來給組中的每個路由加上一個給定的URI,而 name 方法可以用來給每個路由的名字加上一個給定的字串。

這使我們能夠建立新的東西,如管理路由,而不需要修改每一個名稱或字首來識別它們:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Route::name('admin.")->group(function() {
Route::prefix("admin")->group(function() {
Route::get('/get')->name('get');
Route::put('/put')->name(put');
Route::post('/post')->name('post');
});
});
Route::name('admin.")->group(function() { Route::prefix("admin")->group(function() { Route::get('/get')->name('get'); Route::put('/put')->name(put'); Route::post('/post')->name('post'); }); });
 Route::name('admin.")->group(function() {
Route::prefix("admin")->group(function() {
Route::get('/get')->name('get');
Route::put('/put')->name(put');
Route::post('/post')->name('post');
});
});

現在,這些路由的URI將是 admin/getadmin/putadmin/post,以及名稱 admin.getadmin.put, 和 admin.post

路由快取

當把應用程式部署到生產伺服器時, 一個好的Laravel開發者會利用Laravel的路由快取的優勢.

什麼是路由快取?

路由快取減少了註冊所有應用程式的路由所需的時間。

執行 php artisan route:cache ,會生成一個 Illuminate/Routing/RouteCollection 的例項,經過編碼,序列化的輸出被寫入 bootstrap/cache.routes.php

現在任何其他請求都會載入這個快取檔案,如果它存在的話。因此,我們的應用程式不再需要解析和轉換路由檔案中的條目到 Illuminate/Routing/RouteCollection 中的 Illuminate/Routing/Route 物件。

為什麼使用路由快取很重要?

如果不使用Laravel提供的路由快取功能, 你的應用程式有可能執行得更慢, 這可能反過來減少銷售, 使用者保留, 和對你品牌的信任.

根據你的專案的規模和路由的數量, 執行一個簡單的路由快取命令可以使你的應用程式的速度提高130%到500% – 一個巨大的收益,幾乎沒有任何努力。

小結

路由是後臺開發的骨幹。Laravel框架擅長於此, 它提供了一個定義和管理路由的詳細方法.

開發確實可以為每個人所接受,並幫助加快一個應用程式,只是因為它是在Laravel中構建的。

你還遇到過哪些關於Laravel路由的技巧和提示? 請在評論區告訴我們!

評論留言