Chapitre 6Projet SunuLearn

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 inscrit

hasMany / 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 progression

Eager 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.