Zum Hauptinhalt springen

Was ist eine Relation?

Datenbanktabellen stehen häufig in Beziehung zueinander. So kann ein Blog-Beitrag viele Kommentare haben oder eine Bestellung mit dem Nutzer verknüpft sein, der sie aufgegeben hat. Eloquent stellt einen einfachen Mechanismus bereit, um solche Beziehungen (Relationen) zu definieren und mit ihnen zu arbeiten. Relationen werden als Methoden im Eloquent-Modell definiert.
Auf dieser Seite dienen konkrete Modelle wie User, Post, Comment und Tag als Beispiele. Wir gehen davon aus, dass die Modelle und Tabellen bereits vorhanden sind.
Eloquent unterstützt insbesondere folgende Relationen:
RelationBeschreibung
hasOne1:1 (das Elternmodell besitzt ein Kindmodell)
belongsToUmkehrung der 1:1-Relation (das Kindmodell gehört zum Elternmodell)
hasMany1:n (ein Elternmodell besitzt mehrere Kindmodelle)
belongsToManyn:m (nutzt eine Zwischentabelle)

hasOne (1:1)

hasOne beschreibt, dass ein Modell genau eine Instanz eines anderen Modells besitzt. Zum Beispiel besitzt ein User genau ein Profile.

Relation definieren

Fügen Sie im User-Modell eine Methode profile hinzu.
<?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 leitet den Fremdschlüssel automatisch aus dem Elternmodellnamen ab. Hier wird also erwartet, dass die Tabelle profiles eine Spalte user_id besitzt.

Verknüpfte Daten laden

Auf definierte Relationen greifen Sie wie auf Properties zu.
$user = User::find(1);
$profile = $user->profile;
Wird eine Relation-Methode als Property aufgerufen, führt Eloquent automatisch eine Query aus und liefert die verknüpften Daten. Man spricht von „Dynamic Relationship Properties”.

belongsTo (Umkehrung der 1:1-Relation)

belongsTo ist die Umkehrung von hasOne und wird auf der Seite mit dem Fremdschlüssel definiert. Es beschreibt, dass Profile zu einem User gehört.

Relation definieren

<?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 nutzt den Namen der Relationsmethode plus _id als Fremdschlüsselspalte – hier also user_id.

Verknüpfte Daten laden

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

echo $user->name;

hasMany (1:n)

hasMany ist die am häufigsten genutzte Relation: Ein Elternmodell besitzt mehrere Kindmodelle. Zum Beispiel besitzt ein Post mehrere Comments.

Relation definieren

<?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 erwartet, dass die Tabelle comments eine Spalte post_id besitzt.

Verknüpfte Daten laden

Eine hasMany-Relation liefert eine Collection zurück.
$post = Post::find(1);

foreach ($post->comments as $comment) {
    echo $comment->body;
}
Sie können zusätzliche Bedingungen anhängen.
$recentComments = Post::find(1)
    ->comments()
    ->latest()
    ->take(5)
    ->get();

Umkehrung (belongsTo)

Um vom Kommentar zum Beitrag zu navigieren, definieren Sie im Comment-Modell belongsTo.
<?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:m)

Eine n:m-Relation nutzen Sie, wenn beide Modelle jeweils mehrere Verknüpfungen haben können. Zum Beispiel: Ein Post gehört zu mehreren Tags, und ein Tag gehört zu mehreren Posts.

Tabellenaufbau

Für eine n:m-Relation benötigen Sie eine Zwischentabelle. Für Post und Tag legen wir dazu post_tag an.
posts
    id - integer
    title - string

tags
    id - integer
    name - string

post_tag
    post_id - integer
    tag_id - integer
Den Namen der Zwischentabelle leitet Eloquent automatisch ab, indem die beiden Modellnamen alphabetisch verkettet werden (post + tagpost_tag).

Relation definieren

<?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);
    }
}
Analog definieren Sie die Relation auf der Tag-Seite, um sie in beide Richtungen abfragen zu können.
<?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);
    }
}

Verknüpfte Daten laden

$post = Post::find(1);

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

Verknüpfte Datensätze hinzufügen und entfernen

Mit attach fügen Sie Einträge in die Zwischentabelle ein, mit detach entfernen Sie sie.
$post = Post::find(1);

// Tag hinzufügen
$post->tags()->attach($tagId);

// Tag entfernen
$post->tags()->detach($tagId);

// Alle bestehenden Verknüpfungen ersetzen
$post->tags()->sync([$tagId1, $tagId2]);
Mit sync entfernt Eloquent alle Einträge der Zwischentabelle außer den angegebenen IDs, sodass nur die übergebenen IDs als Verknüpfungen bestehen bleiben.

Eager Loading

Was ist das N+1-Problem?

Wenn Sie Relationen als Property abrufen, führt Eloquent bei jedem Zugriff eine eigene Query aus. Das nennt sich „Lazy Loading”. Greifen Sie in einer Schleife auf Relationen zu, entsteht das N+1-Problem.
// Eine Query zum Laden aller Beiträge
$posts = Post::all();

foreach ($posts as $post) {
    // Für jeden Beitrag wird eine eigene Query für den User ausgeführt (N-mal)
    echo $post->user->name;
}
Bei 100 Beiträgen werden insgesamt 101 Queries ausgeführt – ein erheblicher Performance-Nachteil.

Eager Loading mit with()

Mit der Methode with() laden Sie verknüpfte Daten in einem Rutsch, sodass insgesamt nur zwei Queries nötig sind.
// Beiträge und ihre User in zwei Queries laden
$posts = Post::with('user')->get();

foreach ($posts as $post) {
    // Keine zusätzlichen Queries mehr
    echo $post->user->name;
}
Ausgeführt werden nur die folgenden zwei SQL-Statements:
select * from posts

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

Mehrere Relationen gleichzeitig Eager laden

Mit einem Array können Sie mehrere Relationen angeben.
$posts = Post::with(['user', 'comments', 'tags'])->get();

Verschachteltes Eager Loading

Mit Punkt-Notation können auch verschachtelte Relationen Eager geladen werden.
// Kommentare zu Beiträgen und deren Nutzer Eager laden
$posts = Post::with('comments.user')->get();
Eager Loading ist entscheidend, um das N+1-Problem zu vermeiden. Machen Sie es sich zur Gewohnheit, in Schleifen immer with() zu verwenden, wenn Sie auf Relationen zugreifen.

Nächste Schritte

Einführung in Eloquent

Wiederholen Sie die grundlegenden CRUD-Operationen von Eloquent.
Zuletzt geändert am 13. Juli 2026