Passer au contenu principal

Qu’est-ce qu’une relation

Les tables d’une base de données sont souvent liées entre elles. Un article de blog a plusieurs commentaires ; une commande est reliée à l’utilisateur qui l’a passée. Eloquent facilite la définition et la manipulation de ces relations. Elles se déclarent comme des méthodes sur les modèles Eloquent.
Cette page prend User, Post, Comment, Tag comme exemples concrets. Ces modèles et leurs tables sont supposés déjà créés.
Principales relations Eloquent :
RelationDescription
hasOne1-1 (le parent a un seul enfant)
belongsToInverse de 1-1 (l’enfant appartient au parent)
hasMany1-N (le parent a plusieurs enfants)
belongsToManyN-N (via une table pivot)

hasOne (1-1)

hasOne : le modèle possède un seul autre modèle. Par exemple, User a un Profile.

Définir la relation

Ajoutez profile au modèle User.
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasOne;

class User extends Model
{
    public function profile(): HasOne
    {
        return $this->hasOne(Profile::class);
    }
}
Eloquent déduit la clé étrangère du nom du modèle parent : ici, il attend une colonne user_id dans la table profiles.

Récupérer la relation

Accédez à la relation comme une propriété.
$user = User::find(1);
$profile = $user->profile;
Accéder à la méthode comme à une propriété déclenche automatiquement une requête et retourne les données. On parle de « propriété dynamique de relation ».

belongsTo (inverse de 1-1)

belongsTo est l’inverse : à définir sur le modèle qui contient la clé étrangère. Profile appartient à User.

Définir la relation

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Profile extends Model
{
    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }
}
Eloquent utilise le nom de la méthode + _id comme clé étrangère (user_id).

Récupérer la relation

$profile = Profile::find(1);
$user = $profile->user;

echo $user->name;

hasMany (1-N)

hasMany est la relation la plus courante : un parent, plusieurs enfants. Par exemple, un Post a plusieurs Comment.

Définir la relation

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;

class Post extends Model
{
    public function comments(): HasMany
    {
        return $this->hasMany(Comment::class);
    }
}
Eloquent attend une colonne post_id sur comments.

Récupérer la relation

hasMany retourne une Collection.
$post = Post::find(1);

foreach ($post->comments as $comment) {
    echo $comment->body;
}
Vous pouvez ajouter des conditions.
$recentComments = Post::find(1)
    ->comments()
    ->latest()
    ->take(5)
    ->get();

Relation inverse (belongsTo)

Pour remonter d’un commentaire au post, définissez belongsTo dans Comment.
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Comment extends Model
{
    public function post(): BelongsTo
    {
        return $this->belongsTo(Post::class);
    }
}
$comment = Comment::find(1);
echo $comment->post->title;

belongsToMany (N-N)

Une relation N-N s’utilise quand chaque côté peut avoir plusieurs relations. Par exemple, Post a plusieurs Tag et Tag appartient à plusieurs Post.

Structure des tables

Une table pivot est nécessaire. Pour Post et Tag, créez post_tag.
posts
    id - integer
    title - string

tags
    id - integer
    name - string

post_tag
    post_id - integer
    tag_id - integer
Eloquent déduit le nom de la table pivot en combinant les deux noms de modèles par ordre alphabétique (post + tagpost_tag).

Définir la relation

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;

class Post extends Model
{
    public function tags(): BelongsToMany
    {
        return $this->belongsToMany(Tag::class);
    }
}
Définissez la relation inverse dans Tag.
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;

class Tag extends Model
{
    public function posts(): BelongsToMany
    {
        return $this->belongsToMany(Post::class);
    }
}

Récupérer la relation

$post = Post::find(1);

foreach ($post->tags as $tag) {
    echo $tag->name;
}

Ajouter / retirer

attach ajoute des enregistrements dans la pivot ; detach en retire.
$post = Post::find(1);

// Ajouter un tag
$post->tags()->attach($tagId);

// Retirer un tag
$post->tags()->detach($tagId);

// Remplacer toutes les associations actuelles
$post->tags()->sync([$tagId1, $tagId2]);
sync remplace toutes les associations : seules les IDs passées restent, les autres sont supprimées de la pivot.

Eager loading

Problème N+1

Accéder à une relation comme propriété déclenche une requête à chaque fois : c’est du « lazy loading ». Dans une boucle, cela provoque le problème N+1.
// 1 requête pour tous les posts
$posts = Post::all();

foreach ($posts as $post) {
    // 1 requête par post pour récupérer l'utilisateur (N requêtes)
    echo $post->user->name;
}
Avec 100 posts, cela fait 101 requêtes. Grosse perte de performance.

Eager loading avec with()

with() charge la relation en masse : seulement 2 requêtes au total.
// Posts + utilisateurs en 2 requêtes
$posts = Post::with('user')->get();

foreach ($posts as $post) {
    // Aucune requête supplémentaire
    echo $post->user->name;
}
Les 2 SQL exécutés :
select * from posts

select * from users where id in (1, 2, 3, ...)

Charger plusieurs relations

Passez un tableau à with().
$posts = Post::with(['user', 'comments', 'tags'])->get();

Eager loading imbriqué

La notation point permet d’aller plus loin.
// Commentaires des posts + utilisateur de chaque commentaire
$posts = Post::with('comments.user')->get();
Le eager loading est essentiel pour éviter le problème N+1. Prenez l’habitude d’utiliser with() chaque fois que vous accédez à une relation dans une boucle.

Prochaines étapes

Introduction à Eloquent

Revenez sur les opérations CRUD de base d’Eloquent.
Dernière modification le 13 juillet 2026