Dans ce chapitre on va évoquer la partie API de Laravel et on va voir comment gérer la sérialisation de nos modèles en JSON. Par défaut, lorsque l'on retourne directement un modèle dans un controller, Laravel va le convertir en tableau puis en JSON en exposant l'ensemble des attributs du modèle. Dans un cas réel on veut pouvoir sélectionner les champs à exposer via notre API et c'est là que le système de Resource intervient.
Comme d'habitude pour créer ce type de classe on va passer par une commande artisan.
php artisan make:resource PostResource
Ensuite on peut utiliser cette classe dans le controller lorsqu'on souhaite renvoyer les informations d'un modèle.
function show (Post $post) {
return new PostResource($post);
}
Et aussi utiliser la méthode statique dans le cas d'une collection
function index () {
return PostResource::collection(Post::limit(5)->get());
}
Dans la resource il est possible de définir les champs à renvoyer gràce à la méthode toArray()
.
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class PostResource extends JsonResource
{
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'title' => $this->name,
'slug' => $this->email,
'published_at' => $this->published_at
];
}
}
On notera que l'on peut accéder au propriété du modèle en utilisant la variable $this
directement. La class Resource va automatiquement faire proxy et utiliser les propriétés et les méthodes du modèle. Si vous n'êtes pas à l'aise avec cette "magie" vous pouvez aussi accéder à la propriété $resource
qui contiendra le modèle courant.
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
/**
* @property App\Models\Post $resource
**/
class PostResource extends JsonResource
{
public function toArray(Request $request): array
{
return [
'id' => $this->resource->id,
'title' => $this->resource->name,
'slug' => $this->resource->email,
'published_at' => $this->resource->published_at
];
}
}
Il est aussi possible de conditionner la présence d'une propriété à l'aide de divers méthodes comme when()
.
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
/**
* @property App\Models\Post $resource
**/
class PostResource extends JsonResource
{
public function toArray(Request $request): array
{
return [
'id' => $this->resource->id,
'title' => $this->resource->name,
'slug' => $this->resource->email,
'published_at' => $this->resource->published_at,
'created_at' => $this->when($request->user()->isAdmin(), $this->resource->created_at)
];
}
}
Vous avez aussi la possibilité d'inclure des éléments provenant d'une relation, et de ne l'inclure que si la relation a été préchargée.
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
/**
* @property App\Models\Post $resource
**/
class PostResource extends JsonResource
{
public function toArray(Request $request): array
{
return [
'id' => $this->resource->id,
'title' => $this->resource->name,
'slug' => $this->resource->email,
'tags' => TagResource::collection($this->whenLoaded('tags')),
'published_at' => $this->resource->published_at,
];
}
}
Collection
En plus des resources classiques vous pouvez aussi générer des resources qui vont servir à représenter des collections.
php artisan make:resource PostCollection
# si le nom de la classe ne termine pas par "Collection"
php artisan make:resource PostResource --collection
Cette classe possède aussi une méthode toArray()
qui permet de spécifier le retour. Dans cette méthode vous pouvez utiliser la propriété $collection
pour récupérer la collection d'élément.
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\ResourceCollection;
class PostCollection extends ResourceCollection
{
public function toArray($request)
{
return [
'data' => $this->collection,
'meta' => [
'base' => 'https://grafikart.fr/',
],
];
}
}