Laravel to całkiem fajny framework PHP i zapewnia wiele przydatnych funkcji. Jedną z nich jest klasa Resource. Bardzo często pobieramy dane z np. bazy danych i wysyłamy je do naszego klienta aplikacji. Wysłanie całego modelu jest bardzo złą opcją i jest ku temu wiele powodów:
- Prawdopodobnie nie chcemy ujawniać struktury naszych modeli
- Niektóre dane mogą być poufne – być może nasz klient nie będzie korzystał z tych pól, ale każdy użytkownik będzie mógł zajrzeć do żądania, odpowiedzi i uzyskać te dane
- Wielu klientów (np. urządzenia mobilne) nie potrzebuje wszystkich danych
Bez klasy Resource musimy stworzyć własną klasę i dokonać pewnych przekształceń, przygotować dane z bazy danych dla klientów. Jeśli zdecydujemy się na skorzystanie z wbudowanego Zasobu, będzie to znacznie, znacznie prostsze. Wystarczy, że zwrócimy takie instancje klas i przekażemy nasze dane do konstruktora, a następnie napiszemy, jakich pól naprawdę chcemy użyć. Istnieje prosty przykład zasobu Laravel, który przygotuje nasze dane do wysłania jako 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,
(...)
];
}
}
Ten komentarz z $var MyModel jest opcjonalny, ale pomaga niektórym IDE rozpoznać, jakiego modelu użyjemy w naszym zasobie. I jest zastosowanie w naszym kontrolerze:
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)
);
}
Prosty, czysty i elegancki, ponieważ przekształcamy nasz model w osobnym miejscu. Jeśli jest to wymagane, możemy zmodyfikować nasze dane w bardziej złożony sposób, nie ma z tym problemu. Możemy również użyć... Zasób wewnątrz zasobu, więc można zrobić coś takiego:
public function toArray($request)
{
return [
"id" => $this->resource->getKey(),
"name" => $this->resource->my_model_name,
"relation" => new MyModelRelationResource($this->resource->relation),
(...)
];
}
Zasoby
kolekcji Co zrobić, jeśli mamy dużo elementów i chcemy je wysłać w formacie JSON? Nie stanowi to również problemu, ponieważ możemy użyć wbudowanej klasy ResourceCollection, aby to osiągnąć. Jest jeszcze jeden przykład:
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);
}
}
Oczywiście możemy modyfikować lub przekształcać kolekcję w taki sam sposób, jak w normalnym Resource, tylko tablicę odpowiedzi. Zastosowanie w kontrolerze:
public function getModels(Request $request): JsonResponse
{
$models = MyModel::all();
return response()->json(
new MyModuleCollectionResource($models)
);
}
Jak widać, jest bardzo łatwy w użyciu, pozwala nam wszystko lepiej zorganizować i rozwiązać wiele problemów.