NỘI DUNG
Trong bài viết này, tôi xin được chia sẻ với quý độc giả về Route trong Laravel. Cũng giống như các FrameWork khác, Route trong Laravel có chức năng nhận Request từ phía người dùng, tạo ra các đường dẫn ảo (URL) theo ý muốn của người sử dụng, tạo các Action (hành động) cho các đường dẫn này (hiểu nôm na là trỏ tới Controller để xử lý).
Cơ bản routing
Hầu hết các route của laravel cơ cản là nhận một URI và một Closure
, nó cung cấp 1 cách rất đơn giản để định nghĩa một route:
Route::get('foo', function () {
return 'Hello World';
});
File Route mặc định
Tất cả các route được định nghĩa ở trong file route, ở trong thư mục routes
. Nó đó sẽ được tự động tải bởi framework. File routes/web.php
định nghĩa route cho dao diện web của bạn. Đấy là routes được gán vào thuộc nhóm middleware web
, nó cung cấp một số tính năng như session và bảo mật CSRF. File routes/api.php
được gán vào nhóm middleware api
.
Hầu hết các ứng dụng, bạn sẽ bắt đầu định nghĩa route trong file routes/web.php
Một số phương thức có sẵn trong Router
Router cho phép bạn đăng ký routes đáp ứng 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ể đăng ký nhiều routes mà đáp ứng nhiều phương thức HTTP, có thể dùng phương thức match
. Hoặc, bạn có thể đăng ký một routes mà đáp ứng tất cả các phương thức HTTP bằng cách sử dụng phương thức any
:
Route::match(['get', 'post'], '/', function () {
//
});
Route::any('foo', function () {
//
});
Bảo mật CSRF
Tất cả các HTML form có method là POST
, PUT
, hoặc DELETE
đều chỉ đến routes được định nghĩa trong middlware web
thì cần được thêm trường CSRF token. Nếu không thì request sẽ bị từ chối.
<form method="POST" action="/profile">
...
</form>
Các tham số route
Tham số bắt buộc
Tất nhiên, đôi khi bạn cần nắm bắt các segments trong URI bên trong route của bạn. Ví dụ, bạn cần phải lấy ID của người dùng từ các URL. Bạn có thể làm như vậy bằng cách định nghĩa các tham số như sau:
Route::get('user/{id}', function ($id) {
return 'User '.$id;
});
Ngoài ra bạn cũng có thế định nghĩa nhiều tham số theo yêu cầu:
Route::get('posts/{post}/comments/{comment}', function ($postId, $commentId) {
//
});
Tham số route luôn luôn phải nằm trong dấu ngoặc nhọn {}
. Các tham số route không được phép chứa ký tự -
. Bạn có thể dùng ký tự (_
) để thay thế.
Tham số tùy chọn
Thỉnh thoảng, bạn cần phải định nghĩa một route đặc biệt chứa tham số, nhưng sự hiện diện của tham số đấy có thể có hoặc không, bạn có thể dùng cách đặt dấu ?
sau tên tham số, và hãy chắc chắn rằng gán cho nó 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;
});
Tên Routes
Tên routes cho phép đặt tên thuận tiện cho các URL hoặc chuyển hướng cho các route cụ thể. Bạn có chỉ định một tên cho route bằng cách thêm name
vào định nghĩa route :
Route::get('user/profile', function () {
//
})->name('profile');
Ngoài ra bạn cũng có thế chỉ định tên route cho controller:
Route::get('user/profile', 'UserController@showProfile')->name('profile');
Tạo URL từ route đã đặt tên
Một khi bạn đã gán tên cho một route xác định, bạn có thể dùng tên của nó khi tạo URL hoặc chuyển hướng thông qua hàm toàn cục route
:
// Generating URLs...
$url = route('profile');
// Generating Redirects...
return redirect()->route('profile');
Nếu tên route được định nghĩa với tham số, bạn có thể xuyên qua nó như là một đối số thứ hai trong phương thức routeroute
. Các đối số sẽ được chèn vào theo đúng thứ tự chính xác trên URLs:
Route::get('user/{id}/profile', function ($id) {
//
})->name('profile');
$url = route('profile', ['id' => 1]);
Nhóm Route
Nhóm route cho phép bạn chia sẻ các thuộc tính như middleware hoặc namespaces, trên nhiều route mà không cần định nghĩa lại chúng trên mỗi route riêng. Các thuộc tính chia sẻ được quy định trong một mảng định dạng là tham số đầu tiên của phương thức Route::group
.
Middleware
Để gán middleware cho tất cả các route trong một nhóm, bạn phải sử dụng từ khóa middleware
trong mảng thuộc tính. Middleware sẽ được thực hiện theo thứ tự bạn định nghĩa mảng này:
Route::group(['middleware' => 'auth'], function () {
Route::get('/', function () {
// Uses Auth Middleware
});
Route::get('user/profile', function () {
// Uses Auth Middleware
});
});
Namespaces
Một trường hợp sử dụng chung cho nhóm route giống như PHP namespace được chỉ định với một nhóm của controllers. Bạn có thể sử dụng tham số namespace
trong mảng thuộc tính:
Route::group(['namespace' => 'Admin'], function() {
// Controllers Within The "App\Http\Controllers\Admin" Namespace
});
Hãy nhớ rằng, mặc định, the RouteServiceProvider
bao gồm file route bên trong nhóm namespace, cho phép bạn đăng ký các controller routes không cần xác định đầy đủ tiền tố App\Http\Controllers
namespace. Vì vậy, bạn chỉ cần xác định thành phần của tên đó được đưa ra sau namespace App\Http\Controllers
.
Routing tên miền con
Nhóm route có thể được sử dụng để xử lý các routing tên miền con. Tên miền con có thể được gán thám số route như URIs, cho phép bạn lấy một phần của tên miền con để sử dụng bên trong route hoặc controller. Tên miền con có thể được xác định bằng cách sử dụng từ khóadomain
trong mảng thuộc tính:
Route::group(['domain' => '{account}.myapp.com'], function () {
Route::get('user/{id}', function ($account, $id) {
//
});
});
Tiền tố route
Thuộc tính prefix
có thể sử dụng để thêm tiền tố cho mỗi route trong một nhóm với một URI. ví dụ, bạn có thể muốn tất cả các tiền tố của tất cả các route URIs trong nhóm là admin
:
Route::group(['prefix' => 'admin'], function () {
Route::get('users', function () {
// Matches The "/admin/users" URL
});
});
Route Model Binding
Khi bạn inject một model ID vào route hoặc controller, bạn sẽ thường truy vấn để để nhận model tương ứng với ID đó. Laravel route model binding cung cấp một cách khá thuận tiện là tự động inject trực tiếp trường model vào route của bạn. Ví dụ, thay vì bạn inject ID của người dùng, bạn có thể inject toàn bộ model User
phù hợp với ID xác định.
Implicit Binding
Laravel sẽ tự động giải quyết gợi ý Eloquent models được xác định bên trong route hoặc controller có tên biến phù hợp với tên segment. Ví dụ:
Route::get('api/users/{user}', function (App\User $user) {
return $user->email;
});
Trong ví dụ trên, Eloquent đã gợi ý biến $user
định nghĩa trong route phù hợp với {user}
segment trong URI, Laravel tự động đẩy các model có một ID phù hợp với giá trị tương ứng từ URI. Nếu không tìm thấy trong cơ sở dữ liệu, nột phản hồi 404 HTTP sẽ tự động được sinh ra.
Tùy biến tên khóa
Nếu bạn muốn các model ràng buộc ngầm định để suer dụng một cơ sở dữ liệu khác id
khi nhận dữ liệu, bạn có thể ghi đè nên phương thức getRouteKeyName
trong Eloquent model:
public function getRouteKeyName()
{
return 'slug';
}
Explicit Binding
Để đăng ký một explicit binding, sử dụng phương thức model
để xác định class cho một tham số. Bạn nên định nghĩa các explicit model bindings bên trong phương thức boot
của RouteServiceProvider
class:
public function boot()
{
parent::boot();
Route::model('user', App\User::class);
}
Tiếp thep, định nghĩa một route chứa tham số {user}
:
$router->get('profile/{user}', function(App\User $user) {
//
});
Khi chúng ta đã ràng buộc tham số {user}
trong model App\User
, một thể hiện của User
sẽ được inject vào route. Vì vậy, ví dụ, một request đến profile/1
sẽ inject User
có ID là 1
.Nếu thể hiện model không tìm thấy trong cơ sở dữ liệu, một resonse 404 HTTP sẽ tự động được tạo ra.
Tùy chỉnh theo Resolution Logic
Nếu bạn muốn sử dụng resolution logic theo cách riêng của bạn, Bạn có thể dùng phương thức Route::bind
. Thuộc tính Closure
sẽ truyền qua phương thức bind
sẽ nhận được giá trị tham biến trên segment URI và sẽ trả về một thể hiện của class bạn muốn inject vào route:
$router->bind('user', function ($value) {
return App\User::where('name', $value)->first();
});
Form Method Spoofing
HTML forms không hỗ trợ một số method PUT
, PATCH
or DELETE
. Vì vậy, Khi định nghĩa PUT
, PATCH
hoặc DELETE
routes mà được gọi từ HTML form, bạn sẽ cần phải thêm một trường hidden _method
vào form. Giá trị của trường hidden là _method
sẽ sử dụng phương thức HTTP request:
<form action="/foo/bar" method="POST">
<input type="hidden" name="_method" value="PUT">
<input type="hidden" name="_token" value="sALunKiAGdLi8IJkXwm5FiXCLwVLhNJhwHH9xvWA">
</form>
Bạn có thể sử dụng hàm method_field
nó sẽ tự sinh ra một _method
input
Truy cập route hiện tại
Bạn có thể sử dụng phương thức current
, currentRouteName
, và currentRouteAction
trên Route
facade để truy cập thông tin về resquest route xử lý đang đến:
$route = Route::current();
$name = Route::currentRouteName();
$action = Route::currentRouteAction();
Ok. Route trong PHP là như vậy đó, khá là phức tạp, để tìm hiểu kỹ hơn bạn nên thực hành chi tiết từng nội dung.
Chúc các bạn thành công.