Créer une API Laravel, lorsque c'est bien fait, vous offre une base solide sur laquelle une application mobile comme un front-end monopage (SPA) peuvent s'appuyer en toute confiance. Dans cet article, nous ne partirons pas d'une liste vide d'endpoints ; nous concevrons une véritable API REST autour d'un modèle de ressources cohérent, d'une sortie JSON propre et d'une stratégie de versionnage tournée vers l'avenir. L'objectif n'est pas une API qui « fonctionne » simplement, mais une API maintenable, prévisible et à laquelle les clients peuvent se fier.
Penser en ressources, pas en actions
L'essence de la conception RESTful consiste à placer des ressources dans vos URL, et non des actions. Au lieu d'adresses chargées de verbes comme /api/createPost, vous nommez la ressource par un nom et laissez la méthode HTTP exprimer l'action :
GET /api/posts— listerPOST /api/posts— créerGET /api/posts/{id}— afficher un enregistrementPUT/PATCH /api/posts/{id}— mettre à jourDELETE /api/posts/{id}— supprimer
Laravel prend directement en charge ce schéma. La définition Route::apiResource() génère les cinq routes ci-dessus en une seule ligne ; contrairement au resource classique de web.php, elle ignore les routes create et edit qui affichent des formulaires — car une API n'a pas de formulaire HTML.
Définir les routes avec un resource controller
Générez d'abord un contrôleur avec le drapeau --api :
php artisan make:controller Api/V1/PostController --api --model=Post
Puis branchez-le dans routes/api.php en une ligne :
use App\Http\Controllers\Api\V1\PostController;
Route::apiResource('posts', PostController::class);
Cela associe automatiquement les méthodes index, store, show, update et destroy aux verbes HTTP appropriés. Le paramètre de route {post}, lorsqu'il est typé, se transforme directement en l'objet Post correspondant grâce au route model binding de Laravel ; si aucun enregistrement n'est trouvé, Laravel renvoie de lui-même une 404 :
public function show(Post $post)
{
return new PostResource($post);
}
Mettre en forme la sortie JSON avec les API Resources
Renvoyer le modèle directement avec return $post; fonctionne, mais c'est risqué : chaque colonne de la base de données (notes internes, password, horodatages) ressort telle quelle, et le client casse à chaque changement de schéma. Utilisez plutôt une classe API Resource — une couche de transformation où vous définissez explicitement la représentation JSON de votre modèle.
php artisan make:resource PostResource
Vous décidez alors quels champs sortent, et sous quels noms :
public function toArray($request): array
{
return [
'id' => $this->id,
'title' => $this->title,
'body' => $this->body,
'author' => new UserResource($this->whenLoaded('user')),
'created_at' => $this->created_at->toIso8601String(),
];
}
whenLoaded() n'inclut les données relationnelles que lorsqu'elles ont réellement été chargées en eager-loading — un moyen pratique d'éviter le problème de requêtes N+1. Pour renvoyer une collection, vous utilisez PostResource::collection($posts). Si vous souhaitez aussi renvoyer des métadonnées comme le nombre total de pages, vous pouvez passer un paginateur directement dans la resource au sein de index ; Laravel produit automatiquement les liens de pagination sous links et meta.
Validation et réponses d'erreur
Pour valider les données entrantes sans alourdir le contrôleur, les classes Form Request sont idéales :
php artisan make:request StorePostRequest
public function rules(): array
{
return [
'title' => ['required', 'string', 'max:255'],
'body' => ['required', 'string'],
];
}
Lorsque vous la typez dans la méthode du contrôleur, Laravel valide la requête automatiquement ; en cas de violation d'une règle, un client envoyant l'en-tête Accept: application/json reçoit un code 422 Unprocessable Content accompagné de messages d'erreur par champ. C'est la base d'un contrat d'erreur cohérent dans les API REST : 200/201 succès, 401 authentification manquante, 403 non autorisé, 404 introuvable, 422 erreur de validation. Utiliser ces codes de façon cohérente rend la gestion des erreurs côté client prévisible.
Versionnage : préparer l'API pour l'avenir
Une fois une API publiée, la modifier sans casser les clients qui l'utilisent devient difficile. La réponse est le versionnage. La méthode la plus courante et la plus explicite consiste à placer la version dans le chemin de l'URL :
Route::prefix('v1')->group(function () {
Route::apiResource('posts', \App\Http\Controllers\Api\V1\PostController::class);
});
Ainsi /api/v1/posts reste stable ; lorsqu'un changement incompatible devient nécessaire, vous ouvrez une nouvelle version avec un namespace V2 et un préfixe v2, tout en gardant l'ancienne en service un certain temps. Séparer les contrôleurs dans des dossiers de version comme App\Http\Controllers\Api\V1 garde aussi le code physiquement propre. Vous pouvez aussi transporter la version dans l'en-tête Accept (versionnage par media type), mais l'approche basée sur l'URL est plus pratique, tant pour tester dans un navigateur que pour suivre dans les logs.
Authentification et limitation de débit
Pour protéger les endpoints non publics, le paquet Sanctum de Laravel est la solution privilégiée, aussi bien pour les sessions SPA par cookie que pour l'accès par jeton. Vous regroupez les routes protégées avec le middleware auth:sanctum :
Route::middleware('auth:sanctum')->group(function () {
Route::apiResource('posts', PostController::class)
->except(['index', 'show']);
});
Ici, les endpoints de lecture restent publics tandis que ceux d'écriture exigent une authentification. Il est également de bonne pratique d'ajouter une limite de débit avec le middleware throttle pour prévenir les abus ; le RateLimiter de Laravel vous permet de définir le nombre de requêtes par minute par utilisateur ou par IP.
Questions fréquentes
Quelle est la différence entre apiResource et un resource normal ?
Route::resource() génère sept routes, dont deux (create, edit) sont destinées à afficher des formulaires HTML. Route::apiResource() ignore ces deux-là et ne laisse que les cinq routes qui renvoient des données — exactement ce dont vous avez besoin dans une API JSON sans rendu de formulaire.
Pourquoi utiliser une API Resource plutôt que renvoyer le modèle directement ?
Parce qu'une API Resource sépare votre contrat externe de votre schéma de base de données. Même si vous renommez une colonne ou ajoutez un champ sensible, le JSON sortant ne changera pas et ne fuitera pas, sauf si vous le décidez. C'est essentiel à la fois pour la sécurité et la rétrocompatibilité.
Ai-je besoin du versionnage dès le départ ?
Pour un seul petit client, un préfixe v1 n'est pas obligatoire, mais son coût d'ajout est quasi nul. Définir le chemin comme /api/v1 dès le premier jour vous donne une grande souplesse lorsqu'un changement cassant deviendra nécessaire ; l'ajouter plus tard implique de migrer tous les clients.
Vous voulez une base solide pour votre API ? Je peux vous aider à concevoir une API REST Laravel évolutive — des resource controllers au versionnage et à l'authentification. Contactez-moi et planifions votre projet ensemble.