+6

Route Model Binding trong laravel

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\Postnê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

https://laravel.com/docs/5.2/routing


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí