Bài này sẽ đụng chạm tới kiến thức model binding, nên có thể hơi mơ hồ. Nhưng không sao, chúng ta sẽ hiểu nó ở mức độ high-level là được rồi nhé các bạn.

1. Implicit Binding (Binding ngầm)

Xem ví dụ sau

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

Các bạn hiểu đơn giản như này:

  • Chúng ta có một “Eloquent Model” User (App\Models\User)
  • Khi khai báo route /users/{user}. Để ý value của parameter “users” đang có tên là user.
  • Trong callback function, chúng ta đang type-hint Model App\Models\User, và tên variable là $user
  • Lưu ý là tên variable và tên value phải giống nhau.
  • Gỉa sử bây giờ chúng ta gọi route “https://domain/users/1”, có nghĩa value của parameter “users” là 1.
  • Khi này model User sẽ tự động hiểu và truy xuất user có Id = 1
  • Và trả về email: $user->email

Ví dụ thứ 2

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]);
}

Tương tự như vậy, nhưng ở đây chúng ta đang sử dụng controller. Trong hàm show của UserController, chúng ta đang type-hint model User. Lưu ý là tên variable type-hints ($user) phải trùng với tên của parameter segment (/users/{user}).

Thi thoảng chúng ta sẽ muốn sử dụng một column khác thay vì user Id. Hãy xem ví dụ sau

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

Ở đây sẽ sử dụng cloumn “slug” thay vì Id, lưu ý là name của value trong route phải trùng name của variable trong type-hints.

Và thi thoảng bạn muốn model luôn luôn sử dụng một column nào đó (khác cloumn id), bạn có thể dùng hàm getRouteKeyName (viết trong model)

Tức là, khi bạn khai báo route

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

và trong model bạn sử dụng hàm getRouteKeyName

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

Thì lúc này, bạn gọi route: https://domain/posts/slugvalue chẳng hạn, Laravel sẽ hiểu phải dùng cloumn “slug” để truy xuất data thay vì sử dụng cloumn Id

2. Explicit Binding (Binding tường minh)

Như đã giới thiệu ở trên, bạn có thể chỉ ra bind model theo cách implicit. Bạn có thể làm điều tương tự theo cách Explicit.

Bạn có thể khai báo trong hàm boot của AppServiceProvider

Chẳng hạn bạn khai báo router

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

Và khai báo model trong hàm boot.

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

hoặc để custom logic thì bạn làm như sau:

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();
    });
}

Bài này tạm dừng ở đây nhé. Bài sau chúng ta sẽ tìm hiểu về rate limiting. Nghỉ ngơi thôi các bạn 😉

By HNK

Leave a Reply

Your email address will not be published. Required fields are marked *