📚 Table des Matières
Introduction aux API REST
Les API REST (Representational State Transfer) sont devenues la norme pour la communication entre applications. Avec Laravel, créer une API robuste et maintenable est remarquablement simple, grâce à son écosystème riche et sa syntaxe élégante.
Dans ce guide, nous allons créer une API complète pour gérer une base d'utilisateurs, avec toutes les fonctionnalités essentielles : CRUD, authentification, validation, pagination et bien plus encore.
Pour qui est ce guide ?
Ce guide s'adresse aux développeurs ayant déjà une expérience avec Laravel et PHP, et souhaitant approfondir leurs connaissances en développement d'API RESTful.
Configuration de l'environnement
Avant de commencer, assurez-vous d'avoir Laravel installé. Créons un nouveau projet :
composer create-project laravel/laravel api-rest-example
cd api-rest-example
Installez les packages nécessaires pour notre API :
composer require laravel/sanctum
composer require tymon/jwt-auth
Important
Assurez-vous que votre version de PHP est 8.1 ou supérieure. Laravel 10 nécessite PHP 8.1+.
Routes et Controllers
Dans Laravel, les routes sont définies dans le fichier routes/api.php.
Utilisons les routes API Resource pour gérer nos utilisateurs :
use App\Http\Controllers\Api\UserController;
use Illuminate\Support\Facades\Route;
Route::prefix('v1')->group(function () {
// Routes publiques
Route::post('/register', [UserController::class, 'register']);
Route::post('/login', [UserController::class, 'login']);
// Routes protégées
Route::middleware('auth:api')->group(function () {
Route::apiResource('users', UserController::class);
Route::get('/profile', [UserController::class, 'profile']);
Route::put('/profile', [UserController::class, 'updateProfile']);
});
});
Créons maintenant notre contrôleur UserController avec les méthodes CRUD :
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Requests\StoreUserRequest;
use App\Http\Requests\UpdateUserRequest;
use App\Http\Resources\UserResource;
use App\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
class UserController extends Controller
{
/**
* Afficher la liste des utilisateurs
*/
public function index(Request $request): JsonResponse
{
$users = User::query()
->when($request->has('search'), function ($query) use ($request) {
$query->where('name', 'like', '%' . $request->search . '%')
->orWhere('email', 'like', '%' . $request->search . '%');
})
->orderBy('created_at', 'desc')
->paginate($request->get('per_page', 15));
return response()->json([
'success' => true,
'data' => UserResource::collection($users),
'meta' => [
'total' => $users->total(),
'per_page' => $users->perPage(),
'current_page' => $users->currentPage(),
'last_page' => $users->lastPage(),
]
]);
}
/**
* Créer un nouvel utilisateur
*/
public function store(StoreUserRequest $request): JsonResponse
{
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
return response()->json([
'success' => true,
'message' => 'Utilisateur créé avec succès',
'data' => new UserResource($user)
], 201);
}
/**
* Afficher un utilisateur spécifique
*/
public function show(User $user): JsonResponse
{
return response()->json([
'success' => true,
'data' => new UserResource($user)
]);
}
/**
* Mettre à jour un utilisateur
*/
public function update(UpdateUserRequest $request, User $user): JsonResponse
{
$user->update($request->validated());
return response()->json([
'success' => true,
'message' => 'Utilisateur mis à jour avec succès',
'data' => new UserResource($user)
]);
}
/**
* Supprimer un utilisateur
*/
public function destroy(User $user): JsonResponse
{
$user->delete();
return response()->json([
'success' => true,
'message' => 'Utilisateur supprimé avec succès'
]);
}
/**
* Inscription d'un nouvel utilisateur
*/
public function register(StoreUserRequest $request): JsonResponse
{
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
$token = $user->createToken('auth_token')->plainTextToken;
return response()->json([
'success' => true,
'message' => 'Inscription réussie',
'data' => new UserResource($user),
'token' => $token
], 201);
}
/**
* Connexion utilisateur
*/
public function login(Request $request): JsonResponse
{
$request->validate([
'email' => 'required|email',
'password' => 'required'
]);
if (!auth()->attempt($request->only('email', 'password'))) {
return response()->json([
'success' => false,
'message' => 'Identifiants incorrects'
], 401);
}
$user = auth()->user();
$token = $user->createToken('auth_token')->plainTextToken;
return response()->json([
'success' => true,
'message' => 'Connexion réussie',
'data' => new UserResource($user),
'token' => $token
]);
}
/**
* Profil de l'utilisateur connecté
*/
public function profile(): JsonResponse
{
return response()->json([
'success' => true,
'data' => new UserResource(auth()->user())
]);
}
}
Validation des données
La validation est cruciale pour la sécurité de votre API. Utilisons les Form Requests de Laravel :
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rules\Password;
class StoreUserRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return [
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users,email',
'password' => [
'required',
'confirmed',
Password::min(8)
->letters()
->mixedCase()
->numbers()
->symbols()
]
];
}
public function messages(): array
{
return [
'name.required' => 'Le nom est obligatoire',
'email.required' => 'L\'email est obligatoire',
'email.email' => 'L\'email doit être valide',
'email.unique' => 'Cet email est déjà utilisé',
'password.required' => 'Le mot de passe est obligatoire',
'password.confirmed' => 'Les mots de passe ne correspondent pas',
];
}
}
API Resources
Les API Resources permettent de transformer vos modèles en réponses JSON cohérentes :
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class UserResource extends JsonResource
{
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'email_verified_at' => $this->email_verified_at,
'created_at' => $this->created_at->format('Y-m-d H:i:s'),
'updated_at' => $this->updated_at->format('Y-m-d H:i:s'),
'links' => [
'self' => route('api.users.show', $this->id),
'update' => route('api.users.update', $this->id),
'delete' => route('api.users.destroy', $this->id),
]
];
}
}
Tests unitaires
Testez votre API avec PHPUnit pour garantir sa fiabilité :
<?php
namespace Tests\Feature\Api;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Hash;
use Tests\TestCase;
class UserApiTest extends TestCase
{
use RefreshDatabase;
/** @test */
public function it_can_register_a_new_user()
{
$response = $this->postJson('/api/v1/register', [
'name' => 'John Doe',
'email' => 'john@example.com',
'password' => 'Password123!',
'password_confirmation' => 'Password123!'
]);
$response->assertStatus(201)
->assertJsonStructure([
'success',
'message',
'data' => [
'id',
'name',
'email'
],
'token'
]);
$this->assertDatabaseHas('users', [
'email' => 'john@example.com'
]);
}
/** @test */
public function it_can_login_with_valid_credentials()
{
$user = User::factory()->create([
'email' => 'john@example.com',
'password' => Hash::make('Password123!')
]);
$response = $this->postJson('/api/v1/login', [
'email' => 'john@example.com',
'password' => 'Password123!'
]);
$response->assertStatus(200)
->assertJsonStructure([
'success',
'message',
'data',
'token'
]);
}
/** @test */
public function it_can_list_users()
{
User::factory()->count(3)->create();
$user = User::factory()->create();
$response = $this->actingAs($user, 'sanctum')
->getJson('/api/v1/users');
$response->assertStatus(200)
->assertJsonStructure([
'success',
'data',
'meta'
]);
}
}
Bonnes pratiques
Pour maintenir une API de qualité, suivez ces bonnes pratiques :
1. Versionnez votre API
Toujours versionner votre API (v1, v2, etc.) pour assurer la compatibilité avec les clients existants.
2. Utilisez les codes HTTP appropriés
- 200 : Succès
- 201 : Créé
- 400 : Requête invalide
- 401 : Non authentifié
- 403 : Non autorisé
- 404 : Non trouvé
- 422 : Validation échouée
- 500 : Erreur serveur
3. Paginez les résultats
Toujours paginer les résultats de liste pour éviter de surcharger le serveur et le client.
4. Rate Limiting
Implémentez le rate limiting pour protéger votre API contre les abus :
protected $middlewareGroups = [
'api' => [
'throttle:api',
// autres middlewares...
],
];
Prochaines étapes
Maintenant que vous avez une API de base, vous pouvez ajouter des fonctionnalités avancées comme la documentation automatique avec Swagger, la mise en cache Redis, ou l'intégration avec des services tiers.
Vous avez maintenant toutes les bases pour créer une API REST professionnelle avec Laravel. N'hésitez pas à explorer la documentation officielle de Laravel pour approfondir vos connaissances.