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)
);
}
Как видите, он очень прост в использовании, позволяет нам сделать все более организованным и решить множество проблем.