Eloquent: API Resources

1. Lời nói đầu

Dữ nguyên quan điểm lý thuyết là thiểu số chỉ có thực hành mới khiến các bạn hiểu rõ, vì vậy mình sẽ viết một bài chia sẻ một cách chân thực, dễ hiểu với thật nhiều ví dụ để các bạn có những đánh giá chủ quan về các khái niệm tưởng chừng mơ hồ 😃. Ok bắt đầu nào

Chắc mọi người không quá xa là với thuật ngữ API Resources, hay một số bạn đang học thêm một số từ khóa để phù hợp với yêu cầu của doanh nghiệp. Đừng quá lo lắng, trong bài viết này mình sẽ cùng các bạn tìm hiểu về nó, nó dùng để làm gì, nó có tác dụng gì, nó được áp dụng như thế nào, với từng trường hợp cụ thể mình sẽ cố gắng để lấy một ví dụ để các bạn tiện phân tích theo ý kiến chủ quan của bản thân 😄

2. API Resources là gì:

Khi xây dựng API, bạn có thể cần một lớp chuyển đổi nằm giữa các Eloquent model của bạn và JSON responses để trả về cho người dùng ứng dụng của bạn. Laravel's resource classes cho phép bạn chuyển đổi dễ dàng các model và model collections thành JSON.

Hoặc có thể hiểu đơn giản. Ví dụ các bạn lên trên mạng kiếm một api bất kỳ để làm web các bạn tập trung vào đoạn:

Nếu các bạn đã từng tìm hiểu qua front end. Thì mình không quan tâm các bạn dùng ngôn ngữ gì hay xử lý gì ở server, mình sẽ chỉ quan tâm với những trường hợp cụ thể các bạn sẽ trả ra data như thế nào. Và ngược lại mình sẽ không quan tâm bạn dùng ngôn ngữ nào để code giao diện cả, mình cũng chỉ quan tâm với mỗi trường hợp cụ thể mình sẽ trả về một cục data là được. Điều này sẽ tách bạch giữa front end và back-end tiện cho việc code và năng cấp của dự án.

3. Tạo API Resources

Để sử dụng resource trước tiên chúng ta cần tạo 1 model, resource, 1 method trong controller cho table của chúng ta bằng command. Ở đây mình coi như các bạn đã có rồi nhé(Nếu bạn chưa có thì có thể sử dụng lệnh

php artisan make:model name_của_bạn -crmf

để tạo nhanh các file controller, model và factory của bạn nhé) ở đây mình sẽ ví dụ bằng model Product của mình 😄. Bây giời mình sẽ tạo resource Product

php artisan make:resource ProductResource

Các bạn nhớ chú ý cách mình đặt tên để đúng theo format nhé 😄. Câu lệnh trên sẽ tạo một class ProductResourceapp/Http/Resourcesnó sẽ có nội dung như sau:


<?php

namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class ResoureProducts extends JsonResource
{
	public function toArray($request)
    {
        return parent::toArray($request);
    }
}

4. Sử dụng như thế nào

Mặc định trong resource sẽ có sẵn phương thức toArray có nội dung như trên. Các bạn có thể custom lại để phù hợp với trương trình của mình như sau


<?php

namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
use App\Http\Resources\ResourceEvent;

class ResoureProducts extends JsonResource
{
	public function toArray($request)
    {
        'id' => $this->id,
        'name' => $this->name,
        'description' => $this->description,
        'unit_price' => $this->unit_price,
        'events' => new ResourceEvent($this->whenLoaded('event')),
        'created_at' => $this->created_at,
        'updated_at' => $this->updated_at,
    }
}

Và mình sẽ tạo một link route để khi các bạn gọi sẽ trả về cục data trên ra như sau:

Route::get('/', '[email protected]')->name('indexProduct');

Bên method index của file ProductController mình sẽ viết như sau:

public function index()
{
   $products = $this->productRepository->getAll();
  
   return ResoureProducts::collection(Product::with(['event'])->get());
}

Ok đến đây coi như là song phần code rồi đấy !!! bây giờ thay vì mình tiếp tục lấy một số chức năng mở rộng thì mình sẽ phân tích và đi và sẽ chia sẻ về luồng chạy của đoạn code trên nhé 😄.

Đầu tiên nếu các bạn đang sử dụng theo cách cũ là return ra một view thì sẽ thấy đoạn

return ResoureProducts::collection(Product::with(['event'])->get());

thật ra nó cũng không khác nhiều đâu, thay vì truyền các biến sang để ta viết giao diện thì bây giờ chúng ta sẽ trả ra một chuẩn API để thuận tiện trao đổi và đúng theo chuẩn thôi.

Dành cho các bạn chưa biết thì mình biên dịch đoạn code kia là: Gọi đến một resoure ResoureProducts và truyền một mảng giá trị cho nó Product::with(['event'])->get() các bạn chú ý 'event' này là tên của model nhé. À quên các ResoureProducts này là resoure do bạn tạo ở trên nhé 😄. của mình là

use App\Http\Resources\ResoureProducts;

Còn file route thì chắc các bạn cũng biết rồi 😃

Tiếp theo tại ResoureProducts thì các bạn sử dụng $this để lấy tập giá trị trong bộ dữ liệu của mình. Các bạn có thể thấy mình lấy id, name ... ra đúng không ạ 😃. Trong trường hợp đặt biệt ở đây qua 'events' liên kết giữa 2 bảng thì mình muốn lấy về một số thông tin của 'events' này. Để lấy những thông tin mình cần ở event mình cũng custom event này qua file ResourceEvent. Ở đây với quan hệ một event có nhiều product (Hay là tạo ra một cái gì đó) thì mình viết

'events' => new ResourceEvent($this->whenLoaded('event')),

Các bạn đang thắc mắc nếu như đây là một tập hợp, một mảng dữ liệu(Hay là lấy ra một cái gì đó) thì làm sao để lấy ra đúng không ạ !!! thực ra cũng hết sức đơn giản các bạn chỉ cần gọi

'id_event' => ResourceEvent::collection($this->whenLoaded('event')),

Với whenLoaded() có thể hiểu đơn giản là nó sẽ check nếu có tồn tại quan hệ giữa 2 bảng này hay không, nếu có mới thực hiện.

5. Mở rộng

Bài viết đến đây là kết thúc 😄, nhưng mình sẽ chia sẻ thêm một số chức năng mình cảm thấy tương đối hay hay cho một số các bạn muốn tìm hiểu thêm 😄.

Đầu tiên nếu bạn để ý thì chuỗi JSON của bạn sẽ được bảo bọc bởi một data[] như thế này đúng không ạ, điều đôi khi sẽ khi khiến bạn cảm thấy khó chịu khi map trong chương trình của mình khi mà cái gì cũng phải khai báo data[ ]-> cái mà bạn cần. Laravel đã cung cấp cho bạn một cách tuyệt vời để thoát khỏi nó, nơi mà bạn chỉ cần map -> một chân trời mới 😄. Các bạn chỉ cần vào file AppServiceProvider với đường link app/Providers/AppServiceProvider và thêm

Resource::withoutWrapping();

Vào function boot() của mình và chạy thôi. Đơn giản đúng không nào.

Các bạn cũng hoàn toàn có thể xét một trường thỏa mãn điều kiện nào đó mới cho nó hiển thị ra, thường thì là kiểm tra quyền bằng câu lệnh sau

	'secret' => $this->when($this->isAdmin(), 'secret-value'), 

Biên dịch câu lệnh sau sẽ là: Nếu nó thỏa mãn hàm isAdmin() thì nó sẽ thực hiện trả về secret-value các bạn cũng hoàn toàn có thể sử dụng một 'Closure' để thay thế cho secret-value

Tiếp theo là hàm setpivot nếu đúng thì nó sẽ trả về một closore

'expires_at' => $this->whenPivotLoaded('role_users', function () {
        return $this->pivot->expires_at;
}),

Như tên hàm chúng ta có thể hiểu hàm này sẽ lấy về dữ liệu ở bảng phụ pivot để chúng ta custorm các thông tin mà bảng phụ trả về.

6. Kết Luận

Đọc tới đây chắc các bạn cũng đã hình dung được api resours và một số hàm cơ bản trong api resours là gì cũng như cách sử dụng đúng không ạ. Cảm ơn bạn đã đọc bài viết của mình, nếu các bạn có thắc mắc, hay có phần nào chưa hiểu các bạn có thể bình luận dưới phần comment để chúng ta cùng tìm hiểu dõ hơn nhé. Và đặc biệt đừng quên cho mình một like và một share nhé 😃!

All Rights Reserved