> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Introductie tot Eloquent-relaties

> Uitleg over het definiëren van relaties tussen tabellen (één-op-één, één-op-veel, veel-op-veel) met Eloquent en het efficiënt ophalen van gerelateerde data.

## Wat zijn relaties?

Databasetabellen zijn vaak aan elkaar gerelateerd. Een blogpost heeft bijvoorbeeld veel reacties, of een bestelling is gerelateerd aan de gebruiker die haar heeft geplaatst.

Eloquent biedt een mechanisme om zulke relaties tussen tabellen eenvoudig te definiëren en te gebruiken. Relaties definieer je als methoden op je Eloquent-modellen.

<Info>
  Deze pagina gebruikt concrete modellen zoals `User`, `Post`, `Comment` en `Tag` als voorbeeld.
  We gaan ervan uit dat deze modellen en tabellen al zijn aangemaakt.
</Info>

De belangrijkste relaties die Eloquent ondersteunt zijn:

| Relatie         | Beschrijving                                         |
| --------------- | ---------------------------------------------------- |
| `hasOne`        | Eén-op-één (parent heeft één child)                  |
| `belongsTo`     | Omgekeerde van één-op-één (child behoort tot parent) |
| `hasMany`       | Eén-op-veel (parent heeft meerdere children)         |
| `belongsToMany` | Veel-op-veel (met een tussentabel)                   |

```mermaid theme={null}
erDiagram
    users ||--o| profiles : "hasOne / belongsTo (profiles.user_id)"
    posts ||--o{ comments : "hasMany / belongsTo (comments.post_id)"
    posts }o--o{ tags : "belongsToMany (post_tag tussentabel)"
```

## hasOne (één-op-één)

`hasOne` beschrijft een relatie waarbij een model precies één ander model heeft. Bijvoorbeeld wanneer een `User` één `Profile` heeft.

### De relatie definiëren

Definieer een `profile`-methode op het `User`-model.

```php theme={null}
<?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 leidt de foreign key automatisch af uit de naam van het bovenliggende model. In dit geval wordt aangenomen dat de tabel `profiles` een kolom `user_id` heeft.

### Gerelateerde data ophalen

Je kunt de gedefinieerde relatie benaderen als property.

```php theme={null}
$user = User::find(1);
$profile = $user->profile;
```

<Tip>
  Wanneer je een relatiemethode als property aanroept, voert Eloquent automatisch een query uit en geeft het de gerelateerde data terug. Dit heet een "dynamische relatieproperty".
</Tip>

## belongsTo (omgekeerde van één-op-één)

`belongsTo` is het omgekeerde van `hasOne` en definieer je op het model dat de foreign key heeft. Het beschrijft de relatie waarbij een `Profile` tot een `User` behoort.

### De relatie definiëren

```php theme={null}
<?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 gebruikt als foreign key de kolomnaam die bestaat uit de relatiemethodenaam met `_id` erachter (in dit geval `user_id`).

### Gerelateerde data ophalen

```php theme={null}
$profile = Profile::find(1);
$user = $profile->user;

echo $user->name;
```

## hasMany (één-op-veel)

`hasMany` is de meest gebruikte relatie, waarbij één bovenliggend model meerdere onderliggende modellen heeft. Bijvoorbeeld wanneer één `Post` meerdere `Comment`-modellen heeft.

### De relatie definiëren

```php theme={null}
<?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 gaat ervan uit dat de tabel `comments` een kolom `post_id` heeft.

### Gerelateerde data ophalen

Een `hasMany`-relatie geeft een collectie terug.

```php theme={null}
$post = Post::find(1);

foreach ($post->comments as $comment) {
    echo $comment->body;
}
```

Je kunt ook voorwaarden aan de query toevoegen.

```php theme={null}
$recentComments = Post::find(1)
    ->comments()
    ->latest()
    ->take(5)
    ->get();
```

### De omgekeerde relatie (belongsTo)

Om vanuit een reactie naar de post te verwijzen, definieer je `belongsTo` op het `Comment`-model.

```php theme={null}
<?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);
    }
}
```

```php theme={null}
$comment = Comment::find(1);
echo $comment->post->title;
```

## belongsToMany (veel-op-veel)

Een veel-op-veel-relatie gebruik je wanneer beide modellen meerdere relaties met elkaar hebben. Bijvoorbeeld wanneer een `Post` meerdere `Tag`-modellen heeft en een `Tag` ook bij meerdere `Post`-modellen hoort.

### Tabelstructuur

Voor veel-op-veel heb je een tussentabel nodig. In het geval van `Post` en `Tag` maak je een tussentabel genaamd `post_tag`.

```text theme={null}
posts
    id - integer
    title - string

tags
    id - integer
    name - string

post_tag
    post_id - integer
    tag_id - integer
```

<Info>
  De naam van de tussentabel leidt Eloquent automatisch af door de namen van de twee gerelateerde modellen in alfabetische volgorde samen te voegen (`post` + `tag` → `post_tag`).
</Info>

### De relatie definiëren

```php theme={null}
<?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);
    }
}
```

Door hetzelfde te definiëren aan de `Tag`-kant, kun je ook in omgekeerde richting verwijzen.

```php theme={null}
<?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);
    }
}
```

### Gerelateerde data ophalen

```php theme={null}
$post = Post::find(1);

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

### Gerelateerde data toevoegen en verwijderen

Met `attach` voeg je records toe aan de tussentabel, met `detach` verwijder je ze.

```php theme={null}
$post = Post::find(1);

// Een tag toevoegen
$post->tags()->attach($tagId);

// Een tag verwijderen
$post->tags()->detach($tagId);

// Alle huidige relaties vervangen
$post->tags()->sync([$tagId1, $tagId2]);
```

<Tip>
  Met `sync` worden tussentabelrecords met andere ID's dan de opgegeven ID's automatisch verwijderd, zodat alleen de doorgegeven ID's als relatie overblijven.
</Tip>

## Eager loading

### Wat is het N+1-probleem?

Wanneer je een relatie als property benadert, voert Eloquent telkens een query uit. Dit heet "lazy loading". Als je binnen een lus een relatie benadert, ontstaat het N+1-probleem.

```php theme={null}
// Eén query om alle posts op te halen
$posts = Post::all();

foreach ($posts as $post) {
    // Voor elke post wordt een query uitgevoerd om de gebruiker op te halen (N keer)
    echo $post->user->name;
}
```

Bij 100 posts worden in totaal 101 queries uitgevoerd. Dit heeft een grote impact op de prestaties.

### Eager loading met with()

Met de `with()`-methode haal je gerelateerde data in één keer op. Zo blijft het aantal queries beperkt tot slechts twee.

```php theme={null}
// Posts en gebruikers ophalen met twee queries
$posts = Post::with('user')->get();

foreach ($posts as $post) {
    // Er worden geen extra queries uitgevoerd
    echo $post->user->name;
}
```

Er worden maar twee SQL-queries uitgevoerd:

```sql theme={null}
select * from posts

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

### Meerdere relaties tegelijk eager loaden

Je kunt meerdere relaties opgeven met een array.

```php theme={null}
$posts = Post::with(['user', 'comments', 'tags'])->get();
```

### Genest eager loaden

Met de puntnotatie kun je ook geneste relaties eager loaden.

```php theme={null}
// Eager load de reacties op posts en de gebruiker van elke reactie
$posts = Post::with('comments.user')->get();
```

<Warning>
  Eager loading is zeer belangrijk om het N+1-probleem te voorkomen. Maak er een gewoonte van om altijd `with()` te gebruiken wanneer je binnen een lus relaties benadert.
</Warning>

## Volgende stappen

<Card title="Introductie tot Eloquent" icon="database" href="/nl/eloquent">
  Ga terug naar de basis-CRUD-bewerkingen van Eloquent om te herhalen.
</Card>


## Related topics

- [Eloquent API-resources](/nl/eloquent-resources.md)
- [Introductie tot Eloquent](/nl/eloquent.md)
- [Introductie tot authenticatie](/nl/authentication.md)
- [MongoDB](/nl/mongodb.md)
- [Introductie tot Laravel Nightwatch](/nl/blog/nightwatch-introduction.md)
