Laravel - это довольно хороший PHP-фреймворк, который предоставляет множество полезных функций. Одним из них является класс Resource. Очень часто мы получаем какие-то данные из базы данных и отправляем их в клиент нашего приложения. Отправка всей модели — очень плохой вариант, и на это есть много причин:

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

Без класса Resource нам придется создавать свой класс и делать какие-то преобразования, подготавливать данные из базы данных для клиентов. Если мы решим использовать встроенный ресурс, это будет гораздо, намного проще. Нам остается только вернуть такие экземпляры класса и передать наши данные в конструктор, а затем написать, какие поля мы действительно хотим использовать. Есть простой пример Laravel Resource, который подготовит наши данные для отправки в виде 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)
   );
}

Просто, чисто и элегантно, потому что мы трансформируем нашу модель в отдельное место. Если это необходимо, мы можем модифицировать наши данные более сложным способом, с этим нет проблем. Мы также можем использовать... Ресурс внутри Resource, так что можно сделать что-то вроде этого:

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)
   );
}

Как видите, он очень прост в использовании, позволяет нам сделать все более организованным и решить множество проблем.