Các route cơ bản của Laravel chấp nhận một URI và một closure, cung cấp một phương thức định nghĩa route rất đơn giản, dễ hiểu và hoạt động mà không cần có file cấu hình route phức tạp:
use Illuminate\Support\Facades\Route;
Route::get('/greeting', function () {
return 'Hello World';
});
Tất cả các route của Laravel được định nghĩa trong các file route, và được lưu trong thư mục routes
. Các file này được tự động load bởi App\Providers\RouteServiceProvider
của application của bạn. File routes/web.php
định nghĩa các route dành cho giao diện web của bạn. Các route này sẽ được gán với nhóm middleware web
, cung cấp các tính năng như trạng thái session và bảo vệ CSRF. Các route trong routes/api.php
là các route không có trạng thái và được gán với nhóm middleware api
.
Đối với hầu hết các application, bạn sẽ bắt đầu bằng cách định nghĩa các route trong file routes/web.php
. Các route đã được tạo trong file routes/web.php
có thể được truy cập bằng cách nhập URL của route đó vào trong trình duyệt web của bạn. Ví dụ: bạn có thể truy cập vào route sau bằng cách nhập url là http://example.com/user
trong trình duyệt web của bạn:
use App\Http\Controllers\UserController;
Route::get('/user', [UserController::class, 'index']);
Các route được định nghĩa trong file routes/api.php
sẽ nằm trong một nhóm route bởi RouteServiceProvider
. Trong nhóm này, tiền tố URI /api
sẽ được tự động áp dụng, do đó bạn không cần phải tự làm cho mỗi route có trong file. Bạn có thể sửa đổi tiền tố và các tùy chọn khác cho nhóm route này bằng cách sửa đổi trong class RouteServiceProvider
của bạn.
Router cho phép bạn đăng ký route với nhiều phương thức 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);
Thỉnh thoảng, bạn có thể cần phải đăng ký một route với nhiều phương thức từ HTTP. Bạn có thể làm như vậy bằng cách sử dụng phương thức match
. Hoặc, bạn thậm chí có thể đăng ký một route đáp ứng với tất cả các động từ HTTP bằng cách sử dụng phương thức any
:
Route::match(['get', 'post'], '/', function () {
//
});
Route::any('/', function () {
//
});
Note Khi định nghĩa nhiều route có chung một URI, các route sử dụng các phương thức
get
,post
,put
,patch
,delete
vàoptions
phải được định nghĩa trước các routeany
,match
vàredirect
. Điều này giúp đảm bảo request sẽ được khớp với route chính xác.
Bạn có thể khai báo bất kỳ sự phụ thuộc nào mà route của bạn yêu cầu trong định dạng của callback của route. Các phần phụ thuộc này sẽ tự động được resolve và đưa vào lệnh callback bởi service container. Ví dụ: bạn có thể khai báo class Illuminate\Http\Request
để yêu cầu HTTP hiện tại được tự động đưa vào lệnh callback route của bạn:
use Illuminate\Http\Request;
Route::get('/users', function (Request $request) {
// ...
});
Hãy nhớ rằng, bất kỳ form HTML nào mà trỏ đến các route POST
, PUT
, PATCH
hoặc DELETE
mà được định nghĩa trong file route web
, đều phải chứa một field CSRF token. Nếu không có field đó, request sẽ bị từ chối. Bạn có thể đọc thêm về bảo vệ CSRF trong tài liệu CSRF:
<form method="POST" action="/profile">
@csrf
...
</form>
Nếu bạn đang định nghĩa route chuyển hướng đến một URI khác, bạn có thể sử dụng phương thức Route::redirect
. Phương pháp này cung cấp một lối tắt thuận tiện để bạn không phải định nghĩa một route đầy đủ hoặc một controller để thực hiện một chuyển hướng đơn giản:
Route::redirect('/here', '/there');
Mặc định, Route::redirect
sẽ trả về status code là 302
. Bạn có thể tùy chỉnh status code này bằng cách sử dụng tham số thứ ba:
Route::redirect('/here', '/there', 301);
Hoặc, bạn có thể sử dụng phương thức Route::permanentRedirect
để trả về status code là 301
:
Route::permanentRedirect('/here', '/there');
Warning Khi sử dụng tham số route trong route chuyển hướng, các tham số sau sẽ được Laravel dùng sẵn và không thể sử dụng:
destination
vàstatus
.
Nếu route của bạn chỉ cần trả về một view, thì bạn có thể sử dụng phương thức Route::view
. Giống như phương thức redirect
, phương thức này cung cấp một lối tắt đơn giản để bạn không phải định nghĩa một route hoặc một controller đầy đủ. Phương thức view
chấp nhận URI làm tham số đầu tiên và tên view sẽ làm tham số thứ hai. Ngoài ra, bạn có thể cung cấp một mảng data để chuyển đến view dưới dạng là tùy chọn tham số thứ ba:
Route::view('/welcome', 'welcome');
Route::view('/welcome', 'welcome', ['name' => 'Taylor']);
Warning Khi sử dụng tham số route trong view route, các tham số sau sẽ được Laravel dùng sẵn và không thể sử dụng:
view
,data
,status
, vàheaders
.
Lệnh Artisan route:list
có thể dễ dàng cung cấp một cách tổng quan về tất cả các route được ứng dụng của bạn định nghĩa:
php artisan route:list
Mặc định, route middleware mà được gán cho mỗi route sẽ không được hiển thị trong output của lệnh Artisan route:list
; tuy nhiên, bạn có thể bảo Laravel hiển thị route middleware bằng cách thêm tùy chọn -v
vào lệnh:
php artisan route:list -v
Bạn cũng có thể bảo Laravel chỉ hiển thị các route bắt đầu bằng một URI nhất định:
php artisan route:list --path=api
Ngoài ra, bạn có thể bảo Laravel ẩn bất kỳ route nào mà được định nghĩa bởi các package của bên thứ ba bằng cách cung cấp tùy chọn --except-vendor
khi chạy lệnh route:list
:
php artisan route:list --except-vendor
Tương tự như vậy, bạn cũng có thể bảo Laravel chỉ hiển thị các route mà được định nghĩa bởi các package của bên thứ ba bằng cách cung cấp tùy chọn --only-vendor
khi chạy lệnh route:list
:
php artisan route:list --only-vendor
Đôi khi bạn sẽ cần phải lấy các tham số của URI trong route của bạn. Ví dụ: bạn có thể cần lấy ID người dùng từ URL. Bạn có thể làm như vậy bằng cách định nghĩa các route parameter:
Route::get('/user/{id}', function ($id) {
return 'User '.$id;
});
Bạn có thể định nghĩa nhiều route parameter bắt buộc trong route của bạn:
Route::get('/posts/{post}/comments/{comment}', function ($postId, $commentId) {
//
});
Các tham số route luôn nằm trong các dấu ngoặc {}
và phải chứa các ký tự chữ cái. Dấu gạch dưới (_
) cũng được chấp nhận trong tên tham số route. Các tham số route sẽ được inject vào các route callback hoặc controller dựa thoe thứ tự của chúng - tên của các tham số route callback hoặc controller không quan trọng.
Nếu route của bạn có các phần phụ thuộc mà bạn muốn service container của Laravel tự động đưa vào lệnh callback của route, bạn nên liệt kê các tham số route nằm sau phần phụ thuộc của bạn:
use Illuminate\Http\Request;
Route::get('/user/{id}', function (Request $request, $id) {
return 'User '.$id;
});
Đôi khi bạn có thể cần chỉ định một route parameter có thể không phải lúc nào cũng có trong URI. Bạn có thể làm như vậy bằng cách đặt dấu ?
sau tên tham số. Và hãy chắc chắn là biến tương ứng trong route có set một giá trị mặc định:
Route::get('/user/{name?}', function ($name = null) {
return $name;
});
Route::get('/user/{name?}', function ($name = 'John') {
return $name;
});
Bạn có thể hạn chế định dạng của các tham số route của bạn bằng cách sử dụng phương thức where
trên một instance route. Phương thức where
chấp nhận tên của tham số và biểu thức chính quy xác định cách tham số đó bị ràng buộc:
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]+']);
Để thuận tiện, một số pattern biểu thức chính quy thường được sử dụng sẽ có các phương thức helper tương ứng, cho phép bạn nhanh chóng thêm các ràng buộc pattern vào route của bạn:
Route::get('/user/{id}/{name}', function ($id, $name) {
//
})->whereNumber('id')->whereAlpha('name');
Route::get('/user/{name}', function ($name) {
//
})->whereAlphaNumeric('name');
Route::get('/user/{id}', function ($id) {
//
})->whereUuid('id');
Route::get('/user/{id}', function ($id) {
//
})->whereUlid('id');
Route::get('/category/{category}', function ($category) {
//
})->whereIn('category', ['movie', 'song', 'painting']);
Nếu request đến không khớp với các ràng buộc pattern của route, thì response HTTP 404 sẽ được trả về.
Nếu bạn muốn một tham số route luôn bị ràng buộc bởi một biểu thức chính quy định, bạn có thể sử dụng phương thức pattern
. Bạn có thể định nghĩa các pattern này trong phương thức boot
của App\Providers\RouteServiceProvider
:
/**
* Define your route model bindings, pattern filters, etc.
*
* @return void
*/
public function boot()
{
Route::pattern('id', '[0-9]+');
}
Sau khi pattern đã được định nghĩa xong, nó sẽ tự động được áp dụng cho tất cả các route sử dụng tên tham số đó:
Route::get('/user/{id}', function ($id) {
// Only executed if {id} is numeric...
});
Component route của Laravel cho phép tất cả các ký tự được đi qua ngoại trừ ký tự /
có trong các giá trị tham số route. Đối với ký tự /
bạn phải cho phép nó là một phần thay thế bằng cách sử dụng một biểu thức chính quy điều kiện where
:
Route::get('/search/{search}', function ($search) {
return $search;
})->where('search', '.*');
Warning Encoded forward slashes chỉ hỗ trợ tham số cuối cùng của route.
Các tên của route cho phép tạo các URL hoặc các chuyển hướng đến các route cụ thể. Bạn có thể đặt tên cho một route bằng cách kết hợp phương thức name
vào định nghĩa route:
Route::get('/user/profile', function () {
//
})->name('profile');
Bạn cũng có thể đặt tên route cho các hành động của controller:
Route::get(
'/user/profile',
[UserProfileController::class, 'show']
)->name('profile');
Warning Tên route phải luôn là duy nhất.
Khi bạn đã gán tên cho một route, bạn có thể sử dụng tên của route đó khi tạo URL hoặc chuyển hướng đến URL đó bằng phương thức helper route
và redirect
của Laravel:
// Generating URLs...
$url = route('profile');
// Generating Redirects...
return redirect()->route('profile');
return to_route('profile');
Nếu tên route của bạn có định nghĩa tham số, bạn có thể chuyển các tham số đó làm tham số thứ hai trong hàm route
. Các tham số đó sẽ tự động được chèn vào URL được tạo và ở vị trí chính xác của chúng:
Route::get('/user/{id}/profile', function ($id) {
//
})->name('profile');
$url = route('profile', ['id' => 1]);
Nếu bạn truyền thêm các tham số vào mảng, thì các cặp khóa và giá trị của các tham số đó sẽ được tự động thêm vào chuỗi truy vấn của URL đã tạo:
Route::get('/user/{id}/profile', function ($id) {
//
})->name('profile');
$url = route('profile', ['id' => 1, 'photos' => 'yes']);
// /user/1/profile?photos=yes
Note Thỉnh thoảng, bạn có thể muốn chỉ định các giá trị mặc định cho các tham số URL trên toàn bộ request, chẳng hạn như ngôn ngữ hiện tại. Để thực hiện điều này, bạn có thể sử dụng phương thức
URL::defaults
method.
Nếu bạn muốn xác định xem request hiện tại có đúng với một route đã được đặt tên hay không, bạn có thể sử dụng phương thức named
trên một instance route. Ví dụ: bạn có thể kiểm tra tên route hiện tại từ một middleware route:
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if ($request->route()->named('profile')) {
//
}
return $next($request);
}
Nhóm route cho phép bạn chia sẻ các thuộc tính route, chẳng hạn như middleware trên một số lượng lớn các route mà không cần phải định nghĩa các thuộc tính đó trên mỗi route.
Đối với các nhóm lồng nhau thì sẽ thử "merge" các thuộc tính nhóm nhỏ với nhóm to hơn. Middleware và điều kiện where
sẽ được merge trong khi tên và tiền tố sẽ được thêm vào. Dấu phân cách namespace và dấu gạch chéo trong tiền tố URI cũng sẽ tự động được thêm vào chỗ thích hợp.
Để gán middleware cho tất cả các route có trong một nhóm, bạn có thể sử dụng phương thức middleware
ở trước định nghĩa của nhóm route đó. Middleware sẽ thực hiện theo thứ tự mà nó đã được liệt kê trong mảng:
Route::middleware(['first', 'second'])->group(function () {
Route::get('/', function () {
// Uses first & second middleware...
});
Route::get('/user/profile', function () {
// Uses first & second middleware...
});
});
Nếu một nhóm các route đều sử dụng cùng một controller, bạn có thể sử dụng phương thức controller
để định nghĩa một controller chung cho tất cả các route trong nhóm. Sau đó, khi định nghĩa xong các route, bạn chỉ cần cung cấp các phương thức mà chúng gọi:
use App\Http\Controllers\OrderController;
Route::controller(OrderController::class)->group(function () {
Route::get('/orders/{id}', 'show');
Route::post('/orders', 'store');
});
Nhóm route cũng có thể được sử dụng để xử lý các route dành riêng cho tên miền phụ. Tên miền phụ có thể được định nghĩa thông qua tham số route giống như URI route, cho phép bạn lấy một phần tên miền phụ để sử dụng trong route hoặc trong controller của bạn. Tên miền phụ có thể được chỉ định bằng cách gọi phương thức domain
ở trước định nghĩa nhóm route:
Route::domain('{account}.example.com')->group(function () {
Route::get('user/{id}', function ($account, $id) {
//
});
});
Warning Để đảm bảo có thể truy cập được vào các route tên miền phụ của bạn, bạn nên đăng ký các route tên miền phụ của bạn trước khi đăng ký các route tên miền gốc. Điều này sẽ ngăn các route miền gốc ghi đè vào các route tên miền phụ có cùng đường dẫn URI.
Phương thức prefix
có thể được sử dụng để làm tiền tố cho mỗi route trong nhóm route với một URI. Ví dụ: bạn có thể muốn đặt tiền tố cho tất cả các URI của route trong nhóm với tiền tối admin
:
Route::prefix('admin')->group(function () {
Route::get('/users', function () {
// Matches The "/admin/users" URL
});
});
Phương thức name
có thể được sử dụng để đặt tiền tố cho mỗi tên của route trong nhóm với một chuỗi. Ví dụ: bạn có thể muốn đặt tiền tố cho tất cả các tên của route trong một nhóm là admin
. Chuỗi mà đã được đặt làm tiền tố sẽ được gán vào tên của mỗi route, và vì thế chúng ta nên chắc chắn là đã thêm dấu .
vào trong tiền tố để dễ phân biệt tiền tố và tên route:
Route::name('admin.')->group(function () {
Route::get('/users', function () {
// Route assigned name "admin.users"...
})->name('users');
});
Khi inject một model ID vào một route hoặc một controller action, bạn sẽ thường truy vấn database để lấy ra model tương ứng với ID đó ra. Liên kết route model của Laravel sẽ cung cấp một cách để tự động đưa ra các instance của model vào các route của bạn. Ví dụ, thay vì inject user ID, bạn có thể inject một instance model User
khớp với ID đã cho.
Laravel sẽ tự động resolve các model Eloquent được định nghĩa trong các route hoặc trong controller action nếu tên biến khớp với tên tham số route. Ví dụ:
use App\Models\User;
Route::get('/users/{user}', function (User $user) {
return $user->email;
});
Vì biến $user
được khai báo có kiểu là model Eloquent App\Models\User
và tên biến này cũng khớp với tham số URI {user}
, nên Laravel sẽ tự động inject một instance model có ID là giá trị tương ứng từ URI request. Nếu không tìm thấy instance model nào phù hợp trong cơ sở dữ liệu, phản hồi HTTP 404 sẽ được đưa tạo.
Tất nhiên, cũng có thể thực hiện liên kết ngầm khi sử dụng các phương thức controller. Một lần nữa, hãy lưu ý rằng tham số URI {user}
phải khớp với biến $user
trong controller chứa khai báo kiểu App\Models\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]);
}
Thông thường, liên kết model ngầm sẽ không lấy ra các model đã bị soft deleted. Tuy nhiên, bạn có thể hướng dẫn liên kết ngầm để lấy ra các model này bằng cách kết hợp thêm phương thức withTrashed
vào định nghĩa route của bạn:
use App\Models\User;
Route::get('/users/{user}', function (User $user) {
return $user->email;
})->withTrashed();
Thỉnh thoảng bạn có thể muốn resolve các model Eloquent bằng cách sử dụng một cột khác ngoài cột id
. Để làm như vậy, bạn có thể chỉ định cột đó trong định nghĩa tham số route:
use App\Models\Post;
Route::get('/posts/{post:slug}', function (Post $post) {
return $post;
});
Nếu bạn muốn tuỳ biến một liên kết của một model luôn sử dụng một cột khác, khác với cột id
trong cơ sở dữ liệu, bạn có thể ghi đè phương thức getRouteKeyName
trong model Eloquent:
/**
* Get the route key for the model.
*
* @return string
*/
public function getRouteKeyName()
{
return 'slug';
}
Khi liên kết ngầm nhiều model Eloquent trong một định nghĩa route duy nhất, bạn có thể muốn xác định phạm vi của model Eloquent thứ hai sao cho nó phải là con của model Eloquent trước đó. Ví dụ: hãy xem xét định nghĩa route sau để lấy ra một bài đăng blog bằng slug của một người dùng cụ thể:
use App\Models\Post;
use App\Models\User;
Route::get('/users/{user}/posts/{post:slug}', function (User $user, Post $post) {
return $post;
});
Khi sử dụng liên kết ngầm có khóa tùy chỉnh làm tham số route lồng nhau, Laravel sẽ tự động xác định phạm vi truy vấn để lấy ra model lồng nhau của cha mẹ bằng cách sử dụng các quy ước để đoán tên quan hệ trên cha mẹ. Trong trường hợp này, giả định rằng model User
có quan hệ tên là posts
(dạng số nhiều của tên tham số route) có thể được sử dụng để lấy ra model Post
.
Nếu muốn, bạn có thể hướng dẫn Laravel xác định phạm vi liên kết "con" ngay cả khi khóa tùy chỉnh không được cung cấp. Để làm như vậy, bạn có thể gọi phương thức scopeBindings
khi định nghĩa route của bạn:
use App\Models\Post;
use App\Models\User;
Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
return $post;
})->scopeBindings();
Hoặc, bạn có thể hướng dẫn nhóm route sử dụng các liên kết có phạm vi:
Route::scopeBindings()->group(function () {
Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
return $post;
});
});
Tương tự như vậy, bạn có thể hướng dẫn Laravel không giới hạn phạm vi ràng buộc bằng cách gọi phương thức withoutScopedBindings
:
Route::get('/users/{user}/posts/{post:slug}', function (User $user, Post $post) {
return $post;
})->withoutScopedBindings();
Thông thường, response HTTP 404 sẽ được tạo nếu không tìm thấy model liên kết ngầm. Tuy nhiên, bạn có thể tùy chỉnh hành vi này bằng cách gọi phương thức missing
khi định nghĩa route của bạn. Phương thức missing
sẽ chấp nhận một closure sẽ được gọi nếu không thể tìm thấy model liên kết ngầm:
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 đã giới thiệu và hỗ trợ Enums. Để bổ sung thêm cho tính năng này, Laravel cho phép bạn khai báo một string-backed Enum trên một định nghĩa route của bạn và Laravel sẽ chỉ gọi route nếu phân đoạn route đó tương ứng với giá trị Enum hợp lệ. Nếu không trường hợp đó, thì một HTTP response 404 sẽ được trả về. Ví dụ, với Enum sau:
<?php
namespace App\Enums;
enum Category: string
{
case Fruits = 'fruits';
case People = 'people';
}
Bạn có thể định nghĩa một route chỉ được gọi nếu phân đoạn route {category}
là fruits
hoặc people
. Nếu không, thì Laravel sẽ trả về một HTTP response 404:
use App\Enums\Category;
use Illuminate\Support\Facades\Route;
Route::get('/categories/{category}', function (Category $category) {
return $category->value;
});
Bạn không nhất thiết phải sử dụng liên kết ngầm của laravel, cái mà dựa vào quy ước đặt tên. Bạn cũng có thể định nghĩa rõ ràng cách mà các tham số route tương ứng với các model. Để đăng ký một liên kết rõ ràng, hãy sử dụng phương thức model
trong router để định nghĩa một class với một tham số đã cho. Bạn nên định nghĩa các liên kết model rõ ràng của bạn ở đầu phương thức boot
của classRouteServiceProvider
của bạn:
use App\Models\User;
use Illuminate\Support\Facades\Route;
/**
* Define your route model bindings, pattern filters, etc.
*
* @return void
*/
public function boot()
{
Route::model('user', User::class);
// ...
}
Tiếp theo, hãy định nghĩa một route chứa tham số {user}
:
use App\Models\User;
Route::get('/users/{user}', function (User $user) {
//
});
Vì chúng ta đã liên kết các tham số {user}
vào trong model App\Models\User
, nên một instance của class đó sẽ được tự động inject vào trong route của bạn. Vì vậy, ví dụ, nếu một request với uri là users/1
thì sẽ tự động inject instance User
có ID là 1
từ cơ sở dữ liệu.
Nếu không tìm thấy model instance phù hợp trong cơ sở dữ liệu, phản hồi HTTP 404 sẽ được đưa ra.
Nếu bạn muốn định nghĩa một tuỳ chỉnh logic cho liên kết model của bạn, bạn có thể sử dụng phương thức Route::bind
. Closure của bạn sẽ được truyền đến phương thức bind
và nhận vào giá trị của tham số URI, sau đó sẽ trả về một instance của class, và sẽ được inject vào trong route trước đó. Một lần nữa, việc tùy chỉnh này sẽ diễn ra trong phương thức boot
của RouteServiceProvider
trong ứng dụng của bạn:
use App\Models\User;
use Illuminate\Support\Facades\Route;
/**
* Define your route model bindings, pattern filters, etc.
*
* @return void
*/
public function boot()
{
Route::bind('user', function ($value) {
return User::where('name', $value)->firstOrFail();
});
// ...
}
Ngoài ra, bạn có thể ghi đè phương thức resolveRouteBinding
trên model Eloquent của bạn. Phương thức này sẽ nhận vào giá trị phân đoạn của tham số URI và sẽ trả về một instance của class sẽ được đưa vào route:
/**
* 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();
}
Nếu một route đang sử dụng phạm vi liên kết ngầm, phương thức resolveChildRouteBinding
sẽ được sử dụng để resolve liên kết con của model cha:
/**
* 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);
}
Sử dụng phương thức Route::fallback
, bạn có thể định nghĩa một route sẽ được thực thi khi không có một route nào khác phù hợp với request đến. Thông thường, các request chưa được xử lý sẽ tự động hiển thị trang "404" thông qua trình xử lý exception của ứng dụng của bạn. Tuy nhiên, vì bạn hay định nghĩa route fallback
trong file routes/web.php
của bạn, nên tất cả midddleware trong nhóm midddleware web
sẽ được áp dụng cho route này. Tất nhiên, bạn có thể thoải mái thêm midddleware vào trong route này nếu cần:
Route::fallback(function () {
//
});
Warning Route dự phòng phải luôn là route cuối cùng được đăng ký bởi application của bạn.
Laravel có chứa các service giới hạn tỷ lệ mạnh mẽ và có thể tùy chỉnh mà bạn có thể sử dụng để hạn chế lưu lượng truy cập cho một route hoặc một nhóm route nhất định. Để bắt đầu, bạn nên định nghĩa cấu hình giới hạn tỷ lệ đáp ứng nhu cầu của ứng dụng. Thông thường, việc này phải được thực hiện trong phương thức configureRateLimiting
của class App\Providers\RouteServiceProvider
trong ứng dụng của bạn, trong class đó đã chứa sẵn một định nghĩa giới hạn tỷ lệ đã được áp dụng cho các route trong file routes/api.php
trong ứng dụng của bạn:
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
/**
* Configure the rate limiters for the application.
*/
protected function configureRateLimiting(): void
{
RateLimiter::for('api', function (Request $request) {
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
});
}
Giới hạn tỷ lệ được định nghĩa bằng phương thức for
của facade RateLimiter
. Phương thức for
chấp nhận tên giới hạn tỷ lệ và một closure trả về cấu hình giới hạn sẽ được áp dụng cho các route mà được gán cho giới hạn tỷ lệ đó. Cấu hình giới hạn là các instance của class Illuminate\Cache\RateLimiting\Limit
. Class này chứa các phương thức "builder" hữu ích để bạn có thể nhanh chóng định nghĩa giới hạn của bạn. Tên giới hạn tỷ lệ có thể là bất kỳ chuỗi nào bạn muốn:
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
/**
* Configure the rate limiters for the application.
*
* @return void
*/
protected function configureRateLimiting()
{
RateLimiter::for('global', function (Request $request) {
return Limit::perMinute(1000);
});
}
Nếu request gửi đến vượt quá giới hạn tỷ lệ đã chỉ định, Laravel sẽ tự động trả về response có mã trạng thái HTTP 429. Nếu bạn muốn định nghĩa một response khác của riêng bạn sẽ được trả về theo giới hạn tỷ lệ, bạn có thể sử dụng phương thức response
:
RateLimiter::for('global', function (Request $request) {
return Limit::perMinute(1000)->response(function (Request $request, array $headers) {
return response('Custom response...', 429, $headers);
});
});
Vì lệnh callback của giới hạn tỷ lệ sẽ nhận vào một instance request HTTP nên bạn có thể tự động build giới hạn tỷ lệ phù hợp dựa trên request hoặc số lượng người dùng được xác thực:
RateLimiter::for('uploads', function (Request $request) {
return $request->user()->vipCustomer()
? Limit::none()
: Limit::perMinute(100);
});
Thỉnh thoảng bạn có thể muốn phân giới hạn tỷ lệ theo một số giá trị tùy ý. Ví dụ: bạn có thể muốn cho phép người dùng truy cập vào một route nhất định 100 lần mỗi phút cho mỗi địa chỉ IP. Để thực hiện điều này, bạn có thể sử dụng phương thức by
khi xây dựng giới hạn tỷ lệ của bạn:
RateLimiter::for('uploads', function (Request $request) {
return $request->user()->vipCustomer()
? Limit::none()
: Limit::perMinute(100)->by($request->ip());
});
Hãy minh họa tính năng này bằng một ví dụ khác, chúng ta có thể giới hạn quyền truy cập vào route ở mức 100 lần mỗi phút cho mỗi ID người dùng được xác thực hoặc 10 lần mỗi phút cho mỗi địa chỉ IP đối với người chưa đăng nhập:
RateLimiter::for('uploads', function (Request $request) {
return $request->user()
? Limit::perMinute(100)->by($request->user()->id)
: Limit::perMinute(10)->by($request->ip());
});
Nếu cần, bạn có thể trả về một mảng giới hạn tỷ lệ cho một cấu hình giới hạn tỷ lệ nhất định. Mỗi giới hạn tỷ lệ sẽ được đánh giá cho route dựa trên thứ tự chúng được set trong mảng:
RateLimiter::for('login', function (Request $request) {
return [
Limit::perMinute(500),
Limit::perMinute(3)->by($request->input('email')),
];
});
Giới hạn tỷ lệ có thể được gắn vào các route hoặc một nhóm route bằng cách sử dụng throttle
middleware. Middleware throttle sẽ chấp nhận tên của giới hạn tỷ lệ mà bạn muốn gán cho route:
Route::middleware(['throttle:uploads'])->group(function () {
Route::post('/audio', function () {
//
});
Route::post('/video', function () {
//
});
});
Thông thường, middleware throttle
được ánh xạ tới class Illuminate\Routing\Middleware\ThrottleRequests
. Ánh xạ này được định nghĩa trong file HTTP kernelHTTP kernel của ứng dụng của bạn (App\Http\Kernel
). Tuy nhiên, nếu bạn đang sử dụng Redis làm driver cache của ứng dụng, bạn có thể muốn thay đổi ánh xạ này để sử dụng class Illuminate\Routing\Middleware\ThrottleRequestsWithRedis
. Class này hiệu quả hơn trong việc quản lý giới hạn tỷ lệ bằng Redis:
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class,
Các HTML form không hỗ trợ các action PUT
, PATCH
, hoặc DELETE
. Vì vậy, khi định nghĩa các route PUT
, PATCH
, hoặc DELETE
được gửi từ HTML form, bạn sẽ cần phải thêm một input hidden _method
vào form. Giá trị được gửi vào input hidden _method
sẽ được sử dụng làm method request HTTP:
<form action="/example" method="POST">
<input type="hidden" name="_method" value="PUT">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
</form>
Để thuận tiện, bạn có thể dùng lệnh @method
của Blade để tạo ra field input _method
:
<form action="/example" method="POST">
@method('PUT')
@csrf
</form>
Bạn có thể dùng các phương thức current
, currentRouteName
, và currentRouteAction
trong facade Route
để truy cập vào các thông tin của route hiện tại đang được xử lý cho một request:
use Illuminate\Support\Facades\Route;
$route = Route::current(); // Illuminate\Routing\Route
$name = Route::currentRouteName(); // string
$action = Route::currentRouteAction(); // string
Bạn có thể tham khảo tài liệu API cho class facade Route và cả instance Route để biết tất cả các phương thức có sẵn trên facade route và các class route.
Laravel có thể tự động respond các CORS OPTIONS
HTTP request với các giá trị mà bạn đã cấu hình. Tất cả các cài đặt CORS có thể được cấu hình trong file cấu hình config/cors.php
của application. Mặc định, các OPTIONS
request sẽ được tự động xử lý bởi middleware HandleCors
nằm theo trong stack global middleware của bạn. Stack global middleware của bạn nằm trong file HTTP kernel của ứng dụng (App\Http\Kernel
).
Note Để biết thêm thông tin về CORS và header CORS, vui lòng tham khảo tài liệu web MDN về CORS.
Khi deploy ứng dụng của bạn vào production, bạn nên tận dụng cache route của Laravel. Việc sử dụng cache route sẽ giảm đáng kể thời gian cần thiết để đăng ký tất cả các route vào trong ứng dụng của bạn. Để tạo cache route, hãy chạy lệnh Artisan route:cache
:
php artisan route:cache
Sau khi chạy lệnh này, file cache route của bạn sẽ được load theo mọi request. Hãy nhớ rằng, nếu bạn thêm bất kỳ route mới nào vào, thì bạn sẽ cần tạo lại một cache route mới. Vì lý do này, bạn chỉ nên chạy lệnh route:cache
trong quá trình deploy dự án của bạn.
Bạn có thể sử dụng lệnh route:clear
để xóa cache route:
php artisan route:clear
entry