Les relations Eloquent
hasMany, belongsTo, belongsToMany et eager loading
Concepts Théoriques
Les tables de SunuLearn sont liées : une formation appartient à une catégorie, une formation a plusieurs chapitres, un utilisateur peut s'inscrire à plusieurs formations. Eloquent permet de naviguer ces relations avec une syntaxe naturelle :
$formation->category->name; // "Backend"
$formation->chapters; // Collection de chapitres
$user->formations; // Formations où l'utilisateur est inscrithasMany / belongsTo — relation un-à-plusieurs
Une catégorie a PLUSIEURS formations. Une formation appartient à UNE catégorie.
// Category.php
public function formations()
{
return $this->hasMany(Formation::class);
}
// Formation.php
public function category()
{
return $this->belongsTo(Category::class);
}Usage :
$category = Category::find(1);
$category->formations; // Toutes les formations de cette catégorie
$category->formations()->count(); // Nombre de formations
$formation = Formation::find(1);
$formation->category; // L'objet Category
$formation->category->name; // "Backend"hasMany / belongsTo — Formation → Chapters
// Formation.php
public function chapters()
{
return $this->hasMany(Chapter::class)->orderBy('order');
}
// Chapter.php
public function formation()
{
return $this->belongsTo(Formation::class);
}belongsToMany — relation plusieurs-à-plusieurs
Un utilisateur peut s'inscrire à PLUSIEURS formations. Une formation a PLUSIEURS étudiants. La table pivot enrollments fait le lien.
// User.php
public function formations()
{
return $this->belongsToMany(Formation::class, 'enrollments')
->withPivot('progress', 'completed_at')
->withTimestamps();
}
// Formation.php
public function students()
{
return $this->belongsToMany(User::class, 'enrollments')
->withPivot('progress', 'completed_at')
->withTimestamps();
}Usage :
$user->formations; // Formations de l'utilisateur
$user->formations()->attach($formationId); // S'inscrire
$user->formations()->detach($formationId); // Se désinscrire
$user->formations()->updateExistingPivot($id, ['progress' => 50]); // Mettre à jour la progressionEager Loading — éviter le problème N+1
// ❌ Problème N+1 : 1 requête pour les formations + 1 requête par formation pour la catégorie
$formations = Formation::all();
foreach ($formations as $f) {
echo $f->category->name; // Requête SQL à CHAQUE itération !
}
// ✅ Eager loading : 2 requêtes au total (formations + categories)
$formations = Formation::with('category')->get();
foreach ($formations as $f) {
echo $f->category->name; // Pas de requête supplémentaire
}with() charge les relations en amont. Sur 100 formations, ça passe de 101 requêtes à 2. C'est une des optimisations les plus importantes en Laravel.