Route Model Binding trong laravel
Bài đăng này đã không được cập nhật trong 8 năm
Trong laravel, khi chúng ta muốn hiển thị ra hoặc sửa một bài viết hay một thông tin nào đó ta thường truyền vào id của bài viết đó rồi dùng controller truy xuất ra bài viết qua hàm find()
của model tương ứng. Nhưng Laravel đã hỗ trợ chúng ta kết nối giữa model và route để công việc truy xuất dữ liệu trở nên thuận tiện và dễ dàng hơn. Để biết rõ cách dùng tính năng này thế nào chúng ta cùng tìm hiểu cơ chế Route Model Binding trong laravel nhé!
Laravel models binding cung cấp một cách thuận tiện đêr đẩy model vào route. Thay vì đẩy ID của người dùng ta có thể đẩy toàn bộ model User phù hợp với ID xác định được truyền vào route.
Ràng buộc ngầm định
Bình thường chúng ra sẽ viết:
Route::get('view/{id?}', function($id = 0) {
$post = App\Post::find($id);
if (!$post) {
return abort('404');
}
return view('post.view', ['post' => $post]);
});
Thay vào việc viết code như cách 'truyền thống' (bên trên) chúng ta viết như sau và kết quả trả về tương tự như cách 'truyền thống':
Route::get('view/{post?}', function (App\Post $post) {
return view('post.view', ['post' => $post]);
});
Trong ví dụ này, Eloquent đã gợi ý biến $post
định nghĩa trong route
phù hợp với {post}
trong URI. Laravel tự động đẩy đối tượng Model và có ID phù hợp với giá trị tương ứng từ URI vào.
Nếu không tìm thấy trong cơ sở dữ liệu, một phản hồi 404 HTTP
sẽ tự động được tạo ra.
Tùy biến tên khóa
Nếu muốn mô hình ràng buộc ngầm định sử dụng một cột cơ sở dữ liệu khác ID khi lấy dữ liệu thì có thể ghi đè lên phương thức getRouteKeyName
trên Eloquent Model:
class Post extends Model {
public function getRouteKeyName()
{
return 'slug';
}
}
Ràng buộc tường minh
Ràng buộc tham số
Ràng buộc tham số truyền vào route với model tương ứng.
Sử dụng Route facade:
Ví dụ:
Route::model('post', 'App\Post');
Sử dụng phương thức model
của biến $router
trong phương thức RouteServiceProvider::boot
để xác định lớp cần ràng buộc cho một tham số:
Ví dụ:
public function boot(Router $router)
{
parent::boot($router);
$router->model('post', 'App\Post');
}
Xác định route chứa tham số
$router->get('view/{post}', function(App\Post $post) {
//
});
Vì tham số {post}
đã được ràng buộc trong App\Post
nên một thể hiện của Post
sẽ được truyền vào route. Vì vậy, ví dụ, một yêu cầu đến view/1
sẽ truyền Post
có ID là 1 chứ không phải là số 1 như bình thường.
Nếu thể hiện model không được tìm thấy trong cơ sở dữ liệu, một phản ứng 404 HTTP sẽ được tạo ra.
Tùy chỉnh the revolution logic
Ta có thể tùy biến kết quả trả về của việc binding qua hàm bind bằng cách sử dụng Route facade hoặc RouteServiceProvider.
Sử dụng Route facade
Route::bind('post', function ($value) {
return App\Post::find($value)
->where('status', '=', 'published')->first();
});
Sử dụng RouteServiceProvider
Ta sử dụng $router->bind()
trong phương thức RouteServiceProvider::boot
như sau:
public function boot(Router $router)
{
parent::boot($router);
$router->bind('post', function ($value) {
return App\Post::find($value)
->where('status', '=', 'published')->first();
});
}
Thuộc tính bao đóng truyền qua phương thức bind sẽ nhận được giá trị của tham biến trên URI, và sẽ trả về một thể hiện của lớp truyền vào route:
Tùy chỉnh "Not found"
Nếu muốn chỉ đinh hành vi không tìm thấy bản ghi phù hợp trong cơ sở dữ liệu, chúng ta chỉ cần truyền đối số thứ ba của phương thức model:
$router->model('post', 'App\Post', function () {
throw new NotFoundHttpException;
});
Tài liệu tham khảo
All rights reserved