跳到內容

路由

基本路由

最基本的 Laravel 路由接受 URI 和閉包,提供了一種非常簡單且具表現力的方法來定義路由和行為,而無需複雜的路由設定檔

use Illuminate\Support\Facades\Route;
 
Route::get('/greeting', function () {
return 'Hello World';
});

預設路由檔案

所有 Laravel 路由都在您的路由檔案中定義,這些檔案位於 routes 目錄中。這些檔案會由 Laravel 根據您應用程式的 bootstrap/app.php 檔案中指定的設定自動載入。routes/web.php 檔案定義了您網頁介面的路由。這些路由會被指派 web 中介層群組,該群組提供諸如會話狀態和 CSRF 保護等功能。

對於大多數應用程式,您將從定義 routes/web.php 檔案中的路由開始。透過在瀏覽器中輸入已定義路由的 URL,即可存取 routes/web.php 中定義的路由。例如,您可以透過在瀏覽器中導覽至 http://example.com/user 來存取下列路由

use App\Http\Controllers\UserController;
 
Route::get('/user', [UserController::class, 'index']);

API 路由

如果您的應用程式也將提供無狀態 API,您可以使用 install:api Artisan 命令啟用 API 路由

php artisan install:api

install:api 命令會安裝 Laravel Sanctum,它提供了一個穩健但簡單的 API 權杖驗證保護,可用於驗證第三方 API 消費者、SPA 或行動應用程式。此外,install:api 命令會建立 routes/api.php 檔案

Route::get('/user', function (Request $request) {
return $request->user();
})->middleware('auth:sanctum');

routes/api.php 中的路由是無狀態的,並被指派給 api 中介層群組。此外,/api URI 前綴會自動應用於這些路由,因此您不需要手動將其應用於檔案中的每個路由。您可以透過修改應用程式的 bootstrap/app.php 檔案來變更前綴

->withRouting(
api: __DIR__.'/../routes/api.php',
apiPrefix: 'api/admin',
// ...
)

可用的路由器方法

路由器允許您註冊回應任何 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('/', function () {
// ...
});
lightbulb

定義共用相同 URI 的多個路由時,應該在定義使用 anymatchredirect 方法的路由之前,定義使用 getpostputpatchdeleteoptions 方法的路由。這可確保將傳入的請求與正確的路由匹配。

相依性注入

您可以在路由的回呼簽名中輸入您的路由所需的任何相依性。宣告的相依性會由 Laravel 服務容器自動解析並注入到回呼中。例如,您可以輸入 Illuminate\Http\Request 類別,讓目前 HTTP 請求自動注入到您的路由回呼中

use Illuminate\Http\Request;
 
Route::get('/users', function (Request $request) {
// ...
});

CSRF 保護

請記住,指向 web 路由檔案中定義的 POSTPUTPATCHDELETE 路由的任何 HTML 表單都應包含 CSRF 權杖欄位。否則,請求將會被拒絕。您可以在 CSRF 文件中閱讀有關 CSRF 保護的更多資訊

<form method="POST" action="/profile">
@csrf
...
</form>

重新導向路由

如果您要定義重新導向至另一個 URI 的路由,您可以使用 Route::redirect 方法。此方法提供了一個方便的快捷方式,因此您不必為了執行簡單的重新導向而定義完整的路由或控制器

Route::redirect('/here', '/there');

依預設,Route::redirect 會傳回 302 狀態碼。您可以使用選用的第三個參數自訂狀態碼

Route::redirect('/here', '/there', 301);

或者,您可以使用 Route::permanentRedirect 方法來傳回 301 狀態碼

Route::permanentRedirect('/here', '/there');
exclamation

在重新導向路由中使用路由參數時,下列參數會由 Laravel 保留,且無法使用:destinationstatus

視圖路由

如果您的路由只需要傳回一個視圖,您可以使用 Route::view 方法。與 redirect 方法一樣,此方法提供了一個簡單的快捷方式,因此您不必定義完整的路由或控制器。view 方法會接受 URI 作為其第一個引數,並接受視圖名稱作為其第二個引數。此外,您可以提供要傳遞給視圖的資料陣列,作為選用的第三個引數

Route::view('/welcome', 'welcome');
 
Route::view('/welcome', 'welcome', ['name' => 'Taylor']);
exclamation

在視圖路由中使用路由參數時,下列參數會由 Laravel 保留,且無法使用:viewdatastatusheaders

列出您的路由

route:list Artisan 命令可以輕鬆提供由您的應用程式定義的所有路由的概觀

php artisan route:list

依預設,指派給每個路由的路由中介層不會顯示在 route:list 輸出中;但是,您可以指示 Laravel 透過將 -v 選項新增至命令來顯示路由中介層和中介層群組名稱

php artisan route:list -v
 
# Expand middleware groups...
php artisan route:list -vv

您也可以指示 Laravel 只顯示以指定 URI 開頭的路由

php artisan route:list --path=api

此外,您也可以透過在執行 route:list 命令時提供 --except-vendor 選項,指示 Laravel 隱藏由第三方套件定義的任何路由

php artisan route:list --except-vendor

同樣地,您也可以透過在執行 route:list 命令時提供 --only-vendor 選項,指示 Laravel 只顯示由第三方套件定義的路由

php artisan route:list --only-vendor

路由自訂

依預設,您的應用程式路由會由 bootstrap/app.php 檔案設定和載入

<?php
 
use Illuminate\Foundation\Application;
 
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
)->create();

但是,有時您可能想要定義一個全新的檔案來包含應用程式路由的子集。為了達成此目的,您可以向 withRouting 方法提供 then 閉包。在此閉包中,您可以註冊應用程式所需的任何其他路由

use Illuminate\Support\Facades\Route;
 
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
then: function () {
Route::middleware('api')
->prefix('webhooks')
->name('webhooks.')
->group(base_path('routes/webhooks.php'));
},
)

或者,您甚至可以透過向 withRouting 方法提供 using 閉包,完全控制路由註冊。當傳遞此引數時,框架將不會註冊任何 HTTP 路由,您必須負責手動註冊所有路由

use Illuminate\Support\Facades\Route;
 
->withRouting(
commands: __DIR__.'/../routes/console.php',
using: function () {
Route::middleware('api')
->prefix('api')
->group(base_path('routes/api.php'));
 
Route::middleware('web')
->group(base_path('routes/web.php'));
},
)

路由參數

必要參數

有時您需要擷取路由中 URI 的區段。例如,您可能需要從 URL 擷取使用者的 ID。您可以透過定義路由參數來執行此操作

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

您可以定義路由所需的任意多個路由參數

Route::get('/posts/{post}/comments/{comment}', function (string $postId, string $commentId) {
// ...
});

路由參數一律以 {} 大括號括住,且應包含字母字元。底線 (_) 也可接受用於路由參數名稱。路由參數會根據其順序注入到路由回呼/控制器中 - 路由回呼/控制器引數的名稱並不重要。

參數和相依性注入

如果您的路由有相依性,且您希望 Laravel 服務容器自動將這些相依性注入到路由的回呼函式中,您應該將路由參數列在相依性之後。

use Illuminate\Http\Request;
 
Route::get('/user/{id}', function (Request $request, string $id) {
return 'User '.$id;
});

選用參數

有時您可能需要指定一個不一定總是存在於 URI 中的路由參數。您可以在參數名稱後加上 ? 符號來實現這一點。請確保為路由的對應變數提供一個預設值。

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

正規表示式約束

您可以使用路由實例的 where 方法來約束路由參數的格式。where 方法接受參數名稱和一個定義如何約束參數的正規表示式。

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

為了方便起見,一些常用的正規表示式模式有輔助方法,可讓您快速將模式約束新增至路由。

Route::get('/user/{id}/{name}', function (string $id, string $name) {
// ...
})->whereNumber('id')->whereAlpha('name');
 
Route::get('/user/{name}', function (string $name) {
// ...
})->whereAlphaNumeric('name');
 
Route::get('/user/{id}', function (string $id) {
// ...
})->whereUuid('id');
 
Route::get('/user/{id}', function (string $id) {
// ...
})->whereUlid('id');
 
Route::get('/category/{category}', function (string $category) {
// ...
})->whereIn('category', ['movie', 'song', 'painting']);
 
Route::get('/category/{category}', function (string $category) {
// ...
})->whereIn('category', CategoryEnum::cases());

如果傳入的請求與路由模式約束不符,則會傳回 404 HTTP 回應。

全域約束

如果您希望路由參數始終受到給定正規表示式的約束,您可以使用 pattern 方法。您應該在應用程式的 App\Providers\AppServiceProvider 類的 boot 方法中定義這些模式。

use Illuminate\Support\Facades\Route;
 
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Route::pattern('id', '[0-9]+');
}

一旦定義了模式,它會自動套用至所有使用該參數名稱的路由。

Route::get('/user/{id}', function (string $id) {
// Only executed if {id} is numeric...
});

編碼斜線符號

Laravel 路由元件允許除了 / 之外的所有字元出現在路由參數值中。您必須使用 where 條件正規表示式明確允許 / 成為佔位符的一部分。

Route::get('/search/{search}', function (string $search) {
return $search;
})->where('search', '.*');
exclamation

編碼斜線符號僅在最後一個路由片段中受到支援。

命名路由

具名路由允許方便地為特定路由產生 URL 或重新導向。您可以透過在路由定義上鏈式呼叫 name 方法來指定路由的名稱。

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

您也可以為控制器動作指定路由名稱。

Route::get(
'/user/profile',
[UserProfileController::class, 'show']
)->name('profile');
exclamation

路由名稱應始終是唯一的。

為具名路由產生 URL

一旦您為給定路由指定了名稱,您可以在透過 Laravel 的 routeredirect 輔助函式產生 URL 或重新導向時使用路由的名稱。

// Generating URLs...
$url = route('profile');
 
// Generating Redirects...
return redirect()->route('profile');
 
return to_route('profile');

如果具名路由定義了參數,您可以將參數作為第二個引數傳遞給 route 函式。給定的參數將會自動插入到產生的 URL 中正確的位置。

Route::get('/user/{id}/profile', function (string $id) {
// ...
})->name('profile');
 
$url = route('profile', ['id' => 1]);

如果您在陣列中傳遞額外的參數,這些鍵/值對將會自動新增至產生的 URL 的查詢字串中。

Route::get('/user/{id}/profile', function (string $id) {
// ...
})->name('profile');
 
$url = route('profile', ['id' => 1, 'photos' => 'yes']);
 
// /user/1/profile?photos=yes
lightbulb

有時,您可能希望為 URL 參數指定請求範圍的預設值,例如目前的語言環境。為了實現這一點,您可以使用 URL::defaults 方法

檢查目前的路由

如果您想確定目前的請求是否被路由到給定的具名路由,您可以使用 Route 實例的 named 方法。例如,您可以從路由中介軟體檢查目前的路由名稱。

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
 
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
if ($request->route()->named('profile')) {
// ...
}
 
return $next($request);
}

路由群組

路由群組允許您在大量的路由之間共享路由屬性,例如中介軟體,而無需在每個單獨的路由上定義這些屬性。

巢狀群組會嘗試以智慧方式將屬性與其父群組合併。中介軟體和 where 條件會合併,而名稱和前綴會附加。命名空間分隔符號和 URI 前綴中的斜線會在適當的地方自動新增。

中介層

若要將 中介軟體 指派給群組中的所有路由,您可以在定義群組之前使用 middleware 方法。中介軟體會按照它們在陣列中列出的順序執行。

Route::middleware(['first', 'second'])->group(function () {
Route::get('/', function () {
// Uses first & second middleware...
});
 
Route::get('/user/profile', function () {
// Uses first & second middleware...
});
});

控制器

如果一組路由都使用相同的 控制器,您可以使用 controller 方法來定義群組中所有路由的通用控制器。然後,在定義路由時,您只需要提供它們調用的控制器方法。

use App\Http\Controllers\OrderController;
 
Route::controller(OrderController::class)->group(function () {
Route::get('/orders/{id}', 'show');
Route::post('/orders', 'store');
});

子網域路由

路由群組也可以用於處理子網域路由。子網域可以像路由 URI 一樣指派路由參數,允許您捕獲子網域的一部分,以便在路由或控制器中使用。子網域可以透過在定義群組之前呼叫 domain 方法來指定。

Route::domain('{account}.example.com')->group(function () {
Route::get('/user/{id}', function (string $account, string $id) {
// ...
});
});
exclamation

為了確保您的子網域路由可到達,您應該在註冊根網域路由之前註冊子網域路由。這將防止根網域路由覆蓋具有相同 URI 路徑的子網域路由。

路由前綴

prefix 方法可以用來為群組中的每個路由加上給定的 URI 前綴。例如,您可能想要為群組中的所有路由 URI 都加上 admin 前綴。

Route::prefix('admin')->group(function () {
Route::get('/users', function () {
// Matches The "/admin/users" URL
});
});

路由名稱前綴

name 方法可以用來為群組中的每個路由名稱加上給定的字串前綴。例如,您可能想要為群組中的所有路由名稱都加上 admin 前綴。給定的字串會完全按照指定的方式加上路由名稱的前綴,因此我們將確保在前綴中提供尾隨的 . 字元。

Route::name('admin.')->group(function () {
Route::get('/users', function () {
// Route assigned name "admin.users"...
})->name('users');
});

路由模型綁定

當將模型 ID 注入到路由或控制器動作時,您通常會查詢資料庫以擷取對應該 ID 的模型。Laravel 路由模型綁定提供了一種方便的方式,可以直接將模型實例自動注入到您的路由中。例如,您可以注入符合給定 ID 的整個 User 模型實例,而不是注入使用者的 ID。

隱式綁定

Laravel 會自動解析在路由或控制器動作中定義的 Eloquent 模型,這些模型的類型提示變數名稱與路由片段名稱相符。例如

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

由於 $user 變數的類型提示為 App\Models\User Eloquent 模型,且變數名稱與 {user} URI 片段相符,因此 Laravel 會自動注入具有與請求 URI 中對應值相符的 ID 的模型實例。如果在資料庫中找不到相符的模型實例,則會自動產生 404 HTTP 回應。

當然,當使用控制器方法時,也可以進行隱式綁定。再次注意,{user} URI 片段與控制器中包含 App\Models\User 類型提示的 $user 變數相符。

use App\Http\Controllers\UserController;
use App\Models\User;
 
// Route definition...
Route::get('/users/{user}', [UserController::class, 'show']);
 
// Controller method definition...
public function show(User $user)
{
return view('user.profile', ['user' => $user]);
}

軟刪除模型

通常,隱式模型綁定不會擷取已 軟刪除 的模型。但是,您可以透過在路由定義中鏈式呼叫 withTrashed 方法來指示隱式綁定擷取這些模型。

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

自訂鍵

有時您可能希望使用 id 以外的欄位來解析 Eloquent 模型。若要執行此操作,您可以在路由參數定義中指定欄位。

use App\Models\Post;
 
Route::get('/posts/{post:slug}', function (Post $post) {
return $post;
});

如果您希望模型綁定在擷取給定模型類別時始終使用 id 以外的資料庫欄位,您可以在 Eloquent 模型上覆寫 getRouteKeyName 方法。

/**
* Get the route key for the model.
*/
public function getRouteKeyName(): string
{
return 'slug';
}

自訂鍵和範圍

當在單一路由定義中隱式綁定多個 Eloquent 模型時,您可能希望限制第二個 Eloquent 模型的範圍,使其必須是先前 Eloquent 模型的子項。例如,請考慮這個路由定義,它會為特定使用者依 slug 擷取部落格文章。

use App\Models\Post;
use App\Models\User;
 
Route::get('/users/{user}/posts/{post:slug}', function (User $user, Post $post) {
return $post;
});

當使用自訂鍵的隱式綁定作為巢狀路由參數時,Laravel 會自動將查詢範圍限定為透過其父項擷取巢狀模型,並使用慣例來猜測父項上的關係名稱。在這種情況下,將假設 User 模型具有一個名為 posts 的關係(路由參數名稱的複數形式),可用於擷取 Post 模型。

如果您希望,您可以指示 Laravel 即使在未提供自訂鍵時也限制「子」綁定的範圍。若要執行此操作,您可以在定義路由時呼叫 scopeBindings 方法。

use App\Models\Post;
use App\Models\User;
 
Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
return $post;
})->scopeBindings();

或者,您可以指示一整個路由定義群組使用範圍綁定。

Route::scopeBindings()->group(function () {
Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
return $post;
});
});

同樣地,您可以透過呼叫 withoutScopedBindings 方法來明確指示 Laravel 不要限制綁定的範圍。

Route::get('/users/{user}/posts/{post:slug}', function (User $user, Post $post) {
return $post;
})->withoutScopedBindings();

自訂遺失模型行為

通常,如果找不到隱式綁定的模型,則會產生 404 HTTP 回應。但是,您可以透過在定義路由時呼叫 missing 方法來自訂此行為。如果找不到隱式綁定的模型,則會呼叫 missing 方法接受的閉包。

use App\Http\Controllers\LocationsController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redirect;
 
Route::get('/locations/{location:slug}', [LocationsController::class, 'show'])
->name('locations.view')
->missing(function (Request $request) {
return Redirect::route('locations.index');
});

隱式枚舉綁定

PHP 8.1 引入了對 列舉 的支援。為了補充此功能,Laravel 允許您在路由定義上類型提示 backed 列舉,並且只有當該路由片段對應有效的列舉值時,Laravel 才會調用該路由。否則,將自動傳回 404 HTTP 回應。例如,給定以下列舉

<?php
 
namespace App\Enums;
 
enum Category: string
{
case Fruits = 'fruits';
case People = 'people';
}

您可以定義一個路由,只有當 {category} 路由片段為 fruitspeople 時才會調用該路由。否則,Laravel 將傳回 404 HTTP 回應。

use App\Enums\Category;
use Illuminate\Support\Facades\Route;
 
Route::get('/categories/{category}', function (Category $category) {
return $category->value;
});

顯式綁定

您不需要使用 Laravel 基於慣例的隱式模型解析來使用模型綁定。您也可以明確定義路由參數如何對應到模型。若要註冊明確綁定,請使用路由器的 model 方法來指定給定參數的類別。您應該在 AppServiceProvider 類別的 boot 方法開頭定義明確的模型綁定。

use App\Models\User;
use Illuminate\Support\Facades\Route;
 
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Route::model('user', User::class);
}

接下來,定義包含 {user} 參數的路由。

use App\Models\User;
 
Route::get('/users/{user}', function (User $user) {
// ...
});

由於我們已將所有 {user} 參數綁定到 App\Models\User 模型,因此該類別的實例將注入到路由中。因此,舉例來說,對 users/1 的請求將會注入資料庫中 ID 為 1User 實例。

如果在資料庫中找不到相符的模型實例,則會自動產生 404 HTTP 回應。

自訂解析邏輯

如果您希望定義自己的模型綁定解析邏輯,您可以使用 Route::bind 方法。您傳遞給 bind 方法的閉包將會接收 URI 片段的值,並應傳回應注入路由的類別實例。同樣地,此自訂應發生在應用程式的 AppServiceProvider 類的 boot 方法中。

use App\Models\User;
use Illuminate\Support\Facades\Route;
 
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Route::bind('user', function (string $value) {
return User::where('name', $value)->firstOrFail();
});
}

或者,您可以在您的 Eloquent 模型上覆寫 resolveRouteBinding 方法。此方法將接收 URI 段的值,並應傳回應該注入到路由中的類別實例。

/**
* Retrieve the model for a bound value.
*
* @param mixed $value
* @param string|null $field
* @return \Illuminate\Database\Eloquent\Model|null
*/
public function resolveRouteBinding($value, $field = null)
{
return $this->where('name', $value)->firstOrFail();
}

如果路由使用隱式模型綁定作用域,則會使用 resolveChildRouteBinding 方法來解析父模型的子綁定。

/**
* Retrieve the child model for a bound value.
*
* @param string $childType
* @param mixed $value
* @param string|null $field
* @return \Illuminate\Database\Eloquent\Model|null
*/
public function resolveChildRouteBinding($childType, $value, $field)
{
return parent::resolveChildRouteBinding($childType, $value, $field);
}

後備路由

使用 Route::fallback 方法,您可以定義一個路由,當沒有其他路由匹配傳入的請求時,將會執行此路由。通常,未處理的請求會透過您應用程式的異常處理程序自動渲染「404」頁面。但是,由於您通常會在 routes/web.php 檔案中定義 fallback 路由,因此 web 中介層群組中的所有中介層都將應用於該路由。您可以根據需要向此路由新增其他中介層。

Route::fallback(function () {
// ...
});

速率限制

定義速率限制器

Laravel 包含強大且可自訂的速率限制服務,您可以使用這些服務來限制給定路由或路由群組的流量。要開始使用,您應該定義滿足您應用程式需求的速率限制器配置。

速率限制器可以在您應用程式的 App\Providers\AppServiceProvider 類別的 boot 方法中定義。

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
 
/**
* Bootstrap any application services.
*/
protected function boot(): void
{
RateLimiter::for('api', function (Request $request) {
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
});
}

速率限制器使用 RateLimiter Facade 的 for 方法定義。 for 方法接受一個速率限制器名稱和一個閉包,該閉包返回應該應用於分配給該速率限制器的路由的限制配置。限制配置是 Illuminate\Cache\RateLimiting\Limit 類別的實例。此類別包含有用的「建構器」方法,以便您可以快速定義您的限制。速率限制器名稱可以是您想要的任何字串。

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
 
/**
* Bootstrap any application services.
*/
protected function boot(): void
{
RateLimiter::for('global', function (Request $request) {
return Limit::perMinute(1000);
});
}

如果傳入的請求超過指定的速率限制,Laravel 將會自動傳回一個具有 429 HTTP 狀態碼的回應。如果您想定義一個應該由速率限制傳回的自訂回應,您可以使用 response 方法。

RateLimiter::for('global', function (Request $request) {
return Limit::perMinute(1000)->response(function (Request $request, array $headers) {
return response('Custom response...', 429, $headers);
});
});

由於速率限制器回呼接收傳入的 HTTP 請求實例,您可以根據傳入的請求或已驗證的使用者動態建立適當的速率限制。

RateLimiter::for('uploads', function (Request $request) {
return $request->user()->vipCustomer()
? Limit::none()
: Limit::perMinute(100);
});

分割速率限制

有時您可能希望通過一些任意值來分割速率限制。例如,您可能希望允許使用者每分鐘每個 IP 位址存取給定路由 100 次。為此,您可以在建構速率限制時使用 by 方法。

RateLimiter::for('uploads', function (Request $request) {
return $request->user()->vipCustomer()
? Limit::none()
: Limit::perMinute(100)->by($request->ip());
});

為了使用另一個範例說明此功能,我們可以限制每個已驗證的使用者 ID 每分鐘存取該路由 100 次,或訪客每分鐘每個 IP 位址存取 10 次。

RateLimiter::for('uploads', function (Request $request) {
return $request->user()
? Limit::perMinute(100)->by($request->user()->id)
: Limit::perMinute(10)->by($request->ip());
});

多個速率限制

如果需要,您可以為給定的速率限制器配置返回一個速率限制陣列。每個速率限制將根據它們在陣列中的放置順序針對該路由進行評估。

RateLimiter::for('login', function (Request $request) {
return [
Limit::perMinute(500),
Limit::perMinute(3)->by($request->input('email')),
];
});

如果您正在分配多個使用相同 by 值分割的速率限制,則應確保每個 by 值都是唯一的。實現此目的的最簡單方法是在提供給 by 方法的值前面加上前綴。

RateLimiter::for('uploads', function (Request $request) {
return [
Limit::perMinute(10)->by('minute:'.$request->user()->id),
Limit::perDay(1000)->by('day:'.$request->user()->id),
];
});

將速率限制器附加至路由

可以使用 throttle 中介層將速率限制器附加到路由或路由群組。 throttle 中介層接受您要分配給路由的速率限制器的名稱。

Route::middleware(['throttle:uploads'])->group(function () {
Route::post('/audio', function () {
// ...
});
 
Route::post('/video', function () {
// ...
});
});

使用 Redis 進行節流

預設情況下,throttle 中介層會映射到 Illuminate\Routing\Middleware\ThrottleRequests 類別。但是,如果您正在使用 Redis 作為應用程式的快取驅動程式,您可能希望指示 Laravel 使用 Redis 來管理速率限制。為此,您應該在應用程式的 bootstrap/app.php 檔案中使用 throttleWithRedis 方法。此方法將 throttle 中介層映射到 Illuminate\Routing\Middleware\ThrottleRequestsWithRedis 中介層類別。

->withMiddleware(function (Middleware $middleware) {
$middleware->throttleWithRedis();
// ...
})

表單方法偽造

HTML 表單不支援 PUTPATCHDELETE 動作。因此,當定義從 HTML 表單呼叫的 PUTPATCHDELETE 路由時,您需要在表單中新增一個隱藏的 _method 欄位。與 _method 欄位一起傳送的值將用作 HTTP 請求方法。

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

為了方便起見,您可以使用 @method Blade 指令來產生 _method 輸入欄位。

<form action="/example" method="POST">
@method('PUT')
@csrf
</form>

存取目前的路由

您可以使用 Route Facade 上的 currentcurrentRouteNamecurrentRouteAction 方法來存取有關處理傳入請求的路由的資訊。

use Illuminate\Support\Facades\Route;
 
$route = Route::current(); // Illuminate\Routing\Route
$name = Route::currentRouteName(); // string
$action = Route::currentRouteAction(); // string

您可以參考 Route Facade 的底層類別Route 實例的 API 文件,以檢閱路由器和路由類別上可用的所有方法。

跨來源資源共享 (CORS)

Laravel 可以使用您配置的值自動回應 CORS OPTIONS HTTP 請求。 OPTIONS 請求將由自動包含在您應用程式全域中介層堆疊中的 HandleCors 中介層自動處理。

有時,您可能需要自訂應用程式的 CORS 配置值。您可以使用 config:publish Artisan 命令發佈 cors 配置文件來完成此操作。

php artisan config:publish cors

此命令將在您應用程式的 config 目錄中放置一個 cors.php 配置文件。

lightbulb

有關 CORS 和 CORS 標頭的更多資訊,請參閱 MDN 關於 CORS 的 Web 文件

路由快取

將您的應用程式部署到生產環境時,您應該利用 Laravel 的路由快取。使用路由快取將大大減少註冊所有應用程式路由所需的時間。要產生路由快取,請執行 route:cache Artisan 命令。

php artisan route:cache

執行此命令後,您的快取路由檔案將在每個請求時載入。請記住,如果您新增任何新路由,則需要產生新的路由快取。因此,您只應在專案部署期間執行 route:cache 命令。

您可以使用 route:clear 命令清除路由快取。

php artisan route:clear