Laravel Resource API

Giới thiệu

      Trong quá trình làm việc mình có gặp trường hợp viết API bằng Laravel và cần data cuối cùng cần trả về sẽ là JSON và ẩn bớt một vài thông tin không cần thiết đi để phục vụ cho ứng dụng một cách tốt nhất. Hôm nay mình sẽ chia sẻ kiến thức và cách mà mình đã làm cho mọi người nhé.

Đặt vấn đề

Mình có hàm show() như sau:

public function show(Book $book)
{
    return response()->json([
        'data' => [
            'title' => $book->title,
            'description' => $book->description,
            'author' => $book->author->name
        ]
    ]);
}

Hm, trc khi chúng ta response data thì lại cần format lại data.
Thế nếu chúng ta cần thêm 1 attribute nữa thì làm thế nào?
Sau đó nhiều hàm mình cũng dùng lại nó thì sẽ như thế nào?
Hm, suy nghĩ đã?

Tiếp theo mình có hàm update():

public function update(Request $request, Book $book)
{
    $book = $book->update($reques->all());
    return response()->json([
        'data' => [
            'title' => $book->title,
            'description' => $book->description,
            'author' => $book->author->name
        ]
    ]);
}

Hum, lại phải format lần nữa. Mất công quá nhỉ? Một ngày đẹp trời khác mình lại không muốn show cái author ra nữa thì làm thế nào? vào tìm rồi sửa từng đoạn code hả? Căng nhỉ? Liệu có cách nào ngắn gọn hay hơn không?

Laravel Resource là gì?

      Khi xây dựng API, bạn có thể sẽ cần một lớp chuyển đổi nằm từ Model Eloquent sang dạng dữ liệu cuối cùng là Json cho người dùng. Laravel Resource giúp chúng ta chuyển đổi một cách dễ dàng từ model collections sang Json.
Laravel sẽ giải quyết bài toán trên một cách dễ dàng và nhanh gọn với Resource API.
      Laravel resource API được giới thiệu ở phiên bản 5.5 trở đi vì vậy các bạn cần phiên bản >= 5.5 nhé.

Cách thực hiện

Chúng ta có data của user như sau:

   {
        "id": 909,
        "name": "Nguyen Danh LOi",
        "email": "[email protected]",
        "code": "123456",
        "birthday": "2010-10-10",
        "gender": 1,
        "phone": null,
        "mission": "Developer",
        "avatar": "avatar.png",
   }

Chúng ta không cần lấy các field: code, misson, email nữa. Các bước làm như sau:
Sau khi cài Laravel. Chúng ta sẽ tạo 1 resource như sau: Vd: UserResource

php artisan make:resource UserResource

Sau khi chạy lệnh trên chúng ta sẽ thấy xuất hiện thêm thư mục app\Http\Resources
Chúng ta sẽ thấy có UserRessource như sau:

class UserResource extends JsonResource
{
    public function toArray($request)
    {
        return parent::toArray($request);
    }
}

Như đã giới thiệu, Resource này sẽ có tác dụng là chuyển đổi sang kiểu Json để response về data cuối cùng.
Ta thấy có method toArray(), method sẽ return các attributes về kiểu Array để convert về JSON sau đó response về.

Chúng ta sẽ sửa lại thành như sau:

class UserResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'birthday' => $this->birthday,
            'gender' => $this->phone,
            'phone' => $this->phone,
            'mission' => $this->misson,
            'avatar' => $this->avatar
        ];
    }
}

Cách dùng thì sẽ như sau:

Route::get('/user', function () {
    return new UserResource(User::find(1));
});

hoặc:

Route::get('/user', function () {
    return UserResource::collection(User::find(1));
});

Data trả về sẽ như sau:

{
    "data": [
        {
            "id": 1,
            "name": "Nguyen Danh Loi",
            "bỉthday": "2010-10-10",
            "gender": 1,
            "phone": null,
            "mission": "Developer",
            "avatar": "avatar.png",
        }
    ]
}

Thêm 1 attribute nữa thì sao:

class UserResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'birthday' => $this->birthday,
            'gender' => $this->phone,
            'phone' => $this->phone,
            'mission' => $this->misson,
            'avatar' => $this->avatar,
            'status' => 'dep trai'
        ];
    }
}

Nếu có quan hệ nữa thì sao:

class UserResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'birthday' => $this->birthday,
            'gender' => $this->phone,
            'phone' => $this->phone,
            'mission' => $this->misson,
            'avatar' => $this->avatar,
            'status' => 'dep trai',
            'post' => PostResource::collection($this->posts),
        ];
    }
}

nếu bạn muốn chỉ thêm trường posts khi mà quan hệ đã được load thì dùng method whenLoaded:

'post' => Post::collection($this->whenLoaded('posts'))

Mặc định khi data trả về sẽ được wrapping trong 1 mảng data. Để không bị wrap bạn làm như sau: vào app/Provider/AppServiceProvider/

function boot()
    {
        Resource::withoutWrapping();
    }

Trên đây mình đã giới thiệu qua về Resource API. Mong rằng sẽ giúp ích cho các bạn! Cảm ơn các bạn đã đọc bài viết của mình.