J’ai longtemps codé mes APIs Laravel en mode “on verra bien”. Route, contrôleur, quelques tests, on ship. Ça marche — jusqu’au jour où le frontend attend un champ created_at et le backend renvoie date_creation. Trois heures de debug pour un problème de communication.
Le Design-First règle ça. On écrit le contrat avant le code. Tout le monde sait ce qui entre, ce qui sort, et dans quel format.
Le principe
Vous décrivez votre API dans une spec OpenAPI avant de toucher à Laravel. C’est le plan de la maison avant de couler la dalle.
Concrètement, ça donne trois choses :
- Le frontend démarre sans attendre le backend (mock serveur sur la spec)
- Les bugs d’intégration disparaissent quasi complètement
- La doc est déjà faite quand le code est prêt
Écrire le contrat API
On commence par un fichier OpenAPI. Chaque endpoint y est décrit : méthode HTTP, paramètres, formats de requête et réponse, codes d’erreur.
openapi: 3.0.3
info:
title: "API Utilisateurs"
version: "1.0.0"
paths:
/api/users/{id}:
get:
summary: Récupérer un utilisateur par ID
parameters:
- in: path
name: id
required: true
schema:
type: integer
responses:
"200":
description: Utilisateur trouvé
"404":
description: Utilisateur introuvable
Valider la spec en équipe
Ce fichier, je le fais relire par le frontend, la QA, le product. Pas besoin d’une réunion formelle — une PR avec la spec suffit. Chacun commente. Une fois mergé, c’est la source de vérité. On ne négocie plus les formats en plein sprint.
Scaffolder les routes et contrôleurs
La spec est validée. On passe à Laravel.
php artisan make:controller Api/UserController
Dans routes/api.php :
use App\Http\Controllers\Api\UserController;
Route::get('/users/{id}', [UserController::class, 'show']);
Premier réflexe : un stub qui renvoie des données en dur. Le frontend peut brancher ses appels immédiatement.
public function show(int $id)
{
return response()->json([
'id' => $id,
'name' => 'Utilisateur Démo',
]);
}
Brancher la vraie logique
Une fois le stub en place et le frontend qui tourne, on remplace par le vrai code :
use App\Models\User;
public function show(int $id)
{
$user = User::find($id);
if (!$user) {
return response()->json(['error' => 'Utilisateur introuvable'], 404);
}
return response()->json($user, 200);
}
Le contrat ne change pas. Seule l’implémentation évolue. C’est tout l’intérêt.
Valider les entrées
La validation Laravel, c’est du solide. Je m’en sers pour garantir que chaque requête respecte la spec :
use Illuminate\Support\Facades\Validator;
public function store(Request $request)
{
$validator = Validator::make($request->all(), [
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users',
]);
if ($validator->fails()) {
return response()->json(['errors' => $validator->errors()], 400);
}
$user = User::create($request->validated());
return response()->json($user, 201);
}
Des erreurs claires en 400, des données propres en base. Les devs frontend savent exactement quoi afficher quand ça échoue.
Tester contre la spec
Les tests vérifient que l’implémentation colle au contrat. Pas de surprise en prod.
// tests/Feature/UserApiTest.php
public function test_retrieve_existing_user_successfully()
{
$user = User::factory()->create();
$response = $this->getJson("/api/users/{$user->id}");
$response->assertStatus(200)
->assertJson([
'id' => $user->id,
'email' => $user->email,
]);
}
public function test_retrieve_nonexistent_user_returns_404()
{
$response = $this->getJson("/api/users/9999");
$response->assertStatus(404)
->assertJson([
'error' => 'Utilisateur introuvable',
]);
}
Je lance ces tests en CI. Si un dev change un format de réponse sans mettre à jour la spec, le pipeline casse. C’est voulu.
Générer la doc
Dernier maillon : la documentation auto-générée depuis la spec. L5-Swagger fait le travail :
composer require darkaonline/l5-swagger
php artisan l5-swagger:generate
La doc reste synchronisée avec le code. Plus de wiki obsolète que personne ne met à jour.
Ce que ça change au quotidien
Sur mes derniers projets Laravel, le Design-First a tué une catégorie entière de bugs — ceux liés aux malentendus entre frontend et backend. Le temps investi dans la spec se récupère dès la première intégration. Et quand un nouveau dev rejoint l’équipe, la spec OpenAPI lui donne le contexte en cinq minutes au lieu d’une demi-journée de fouille dans le code.