TL;DR : Appliquez la methodologie API Design-First dans Laravel avec des packages dedies. Ecrivez votre spec OpenAPI, generez routes et requests avec
laravel-openapi, validez avec Spectral, et lancez des tests de contrat en CI. La spec guide l’implementation — pas l’inverse.
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.
Questions frequentes
Peut-on utiliser API Design-First sur un projet Laravel existant ?
Oui. Commencez par documenter vos endpoints actuels dans une spec OpenAPI, puis adoptez progressivement le workflow spec-first pour les nouveaux endpoints. Pas besoin de tout reecrire.
Quels packages Laravel supportent le developpement Design-First ?
Les packages cles incluent laravel-openapi pour la generation de routes/requests depuis les specs, laravel-data pour les DTOs types, et Spectral (npm) pour le linting de specs.
Comment valider les reponses API contre la spec OpenAPI dans Laravel ?
Utilisez un middleware qui verifie les formes de reponse contre votre spec pendant les tests. Des packages comme openapi-httpfoundation-testing peuvent valider que vos reponses correspondent aux schemas declares.
Faut-il versionner la spec OpenAPI dans Git ?
Absolument. Le fichier de spec doit vivre dans votre depot a cote du code. Utilisez des pull requests pour revoir les changements de spec avant l’implementation.