Tìm hiểu về Route trong Laravel

Laravel

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à POSTPUT, 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 middlewaretrong 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\Controllersnamespace. 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 prefixcó 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 PUTPATCH or DELETE. Vì vậy, Khi định nghĩa PUTPATCHhoặc DELETE routes mà được gọi từ HTML form, bạn sẽ cần phải thêm một trường hidden _methodvà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 currentcurrentRouteName, và currentRouteAction trên Routefacade để 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.

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *