Laravel — це досить гарний PHP-фреймворк, який надає багато корисних функцій. Одним з них є клас Ресурс. Дуже часто ми отримуємо якісь дані з колишньої бази даних і відправляємо їх клієнту нашого додатку. Відправка всієї моделі - дуже поганий варіант, і на це є багато причин:

  • Ми, мабуть, не хочемо розкривати структуру наших моделей
  • Деякі дані можуть бути конфіденційними – можливо, наш клієнт не буде використовувати ці поля, але кожен користувач зможе подивитися запит, відповідь і отримати ці дані
  • Багатьом клієнтам (наприклад, мобільним пристроям) не потрібні всі дані

Без класу Resource нам доводиться створювати власний клас і робити деякі перетворення, готувати дані з бази даних для клієнтів. Якщо ми вирішимо використовувати вбудований Ресурс, це буде набагато, набагато простіше. Нам залишається тільки повернути такі екземпляри класів і передати наші дані в конструктор, а потім написати, які поля ми дійсно хочемо використовувати. Є простий приклад ресурсу Laravel, який підготує наші дані для відправки у форматі JSON:

declare(strict_types=1);
namespace App\Modules\MyModule\Resources;
use Illuminate\Http\Resources\Json\Resource;
class MyModelResource extends Resource
{
   /**
    * @var MyModel
    */
   public $resource;
   public function toArray($request)
   {
      return [
       “id” => $this->resource->getKey(),
       “name” => $this->resource->my_model_name,
       “count” => $this->resource->my_model_attribute,
       (...)
      ];
   }
}

Цей коментар з $var MyModel є необов'язковим, але допомагає деяким IDE розпізнати, яку модель ми будемо використовувати в нашому ресурсі. І в нашому контролері є застосування:

public function getModel(Request $request): JsonResponse
{
   // here some code for get model (or inject it with route)
   $model = MyModel::find($request->id);   
   return response()->json(
       new MyModelResource($model)
   );
}

Просто, чисто і елегантно, адже ми трансформуємо нашу модель в окремому місці. Якщо це необхідно, ми можемо змінити наші дані більш складним чином, без проблем. Ми також можемо використовувати... Ресурс всередині ресурсу, тому можна зробити щось на кшталт цього:

public function toArray($request)
{
    return [
        "id" => $this->resource->getKey(),
        "name" => $this->resource->my_model_name,
        "relation" => new MyModelRelationResource($this->resource->relation),
        (...)
  ];
}

Колекційні ресурси

Що робити, якщо у нас багато елементів і ми хочемо надіслати їх у форматі JSON? Це також не проблема, тому що для цього ми можемо використовувати вбудований клас ResourceCollection. Є ще один приклад:

declare(strict_types=1);
namespace App\Modules\MyModule\Resources;

use Illuminate\Http\Resources\Json\ResourceCollection;
class MyModuleCollectionResource extends ResourceCollection
{
   public function toArray($request)
   {
       return MyModuleResource::collection($this->collection);
   }
}

Звичайно, ми можемо модифікувати або трансформувати колекцію так само, як і в звичайному Resource, просто масив відповідей. Використання в контролері:

public function getModels(Request $request): JsonResponse
{
   $models = MyModel::all();   
   return response()->json(
       new MyModuleCollectionResource($models)
   );
}

Як бачите, він дуже простий у використанні, дозволяє нам зробити все більш організованим і вирішити багато питань.