Naar de inhoud
Recognized by Laravel Match je project Contact

Voorkom N+1 queries

Voor het laatst bijgewerkt op:

Omschrijving

Voorkom lazy loading van Eloquent-relaties in loops door gerelateerde data en counts vooraf eager te laden.

Aanbevolen situatie

Gebruik dit wanneer code collecties van modellen weergeeft of verwerkt en gerelateerde Eloquent-data nodig heeft.

Menselijke begeleiding

N+1 query-problemen behoren tot de meest voorkomende performanceproblemen in Laravel-applicaties. Ze ontstaan wanneer code een collectie modellen laadt en vervolgens op elk model afzonderlijk een relatie aanspreekt, wat resulteert in één query voor de collectie plus één query per model. Laravel biedt verschillende tools om dit te voorkomen, waaronder eager loading met with(), preventLazyLoading(), withCount() en het selectief laden van kolommen.

Waarom

  • Drastisch minder queries: Eager loading met with() reduceert N+1 queries tot slechts 2 queries in totaal, ongeacht de grootte van de collectie
  • Vroegtijdige detectie: Het inschakelen van preventLazyLoading() tijdens ontwikkeling vangt N+1 problemen op voordat ze in productie belanden
  • Efficiënt tellen: Het gebruik van withCount() voorkomt dat volledige relaties worden geladen alleen maar om ze te tellen
  • Lager geheugengebruik: Door alleen de benodigde kolommen te selecteren voorkom je dat grote tekst- of JSON-velden onnodig worden geladen

Geschikt voor

  • Elke applicatie die relaties laadt op collecties van modellen
  • Views of API-responses die gerelateerde modeldata weergeven
  • Applicaties met groeiende datasets waarbij het aantal queries van belang is
  • Projecten met meerdere ontwikkelaars waar N+1 problemen makkelijk worden geïntroduceerd

Minder geschikt voor

  • Eenvoudige applicaties met minimale relaties
  • Opzoekacties op een enkel model waarbij slechts één gerelateerde query wordt uitgevoerd

Voorbeelden

Laad relaties altijd eager

// Slecht: N+1, voert 1 + N queries uit
$posts = Post::all();
foreach ($posts as $post) {
    echo $post->author->name;
}

// Goed: 2 queries in totaal
$posts = Post::with('author')->get();
foreach ($posts as $post) {
    echo $post->author->name;
}

Beperk eager loads zodat ze alleen de benodigde kolommen selecteren (voeg altijd de foreign key toe):

$users = User::with(['posts' => function ($query) {
    $query->select('id', 'user_id', 'title')
          ->where('published', true)
          ->latest()
          ->limit(10);
}])->get();

Voorkom lazy loading tijdens ontwikkeling

Schakel dit in binnen AppServiceProvider::boot() om N+1 problemen tijdens ontwikkeling op te vangen:

public function boot(): void
{
    Model::preventLazyLoading(! app()->isProduction());
}

Dit gooit een LazyLoadingViolationException wanneer een relatie wordt aangesproken zonder eager te zijn geladen.

Gebruik withCount() voor het tellen van relaties

// Slecht: laadt volledige collecties alleen maar om ze te tellen
$posts = Post::all();
foreach ($posts as $post) {
    echo $post->comments->count();
}

// Goed: voegt een comments_count-attribuut toe via een enkele subquery
$posts = Post::withCount('comments')->get();
foreach ($posts as $post) {
    echo $post->comments_count;
}

Selecteer alleen de benodigde kolommen

// Slecht: SELECT * op beide tabellen
$posts = Post::with('author')->get();

// Goed: haalt alleen op wat je nodig hebt
$posts = Post::select('id', 'title', 'user_id', 'created_at')
    ->with(['author:id,name,avatar'])
    ->get();

Wanneer je kolommen selecteert op eager-geladen relaties, voeg dan altijd de foreign key-kolom toe, anders matcht de relatie niet.

Meer informatie

Boost guideline

---
title: Prevent N+1 Queries
description: Prevent Eloquent relationship lazy loading in loops by eager loading related data and counts up front.
recommended_situation: Use when code renders or processes collections of models and needs related Eloquent data.
---

- Eager load every relationship that will be accessed inside loops, collections, API resources, or views.
- Use `withCount()` or aggregate queries when only counts or summary values are needed.
- Select only the columns you need on the root query and eager-loaded relationships, including required foreign keys.
- Enable `Model::preventLazyLoading(! app()->isProduction())` in development to catch regressions early.
Skill

Laravel Boost Skill

Gebruik deze skill om de richtlijn rechtstreeks toe te passen met een AI-assistent.

Use this skill when a Laravel task touches this best practice. It is self-contained so it can be installed independently by Laravel Boost or another agent-skill system.

## Core Guidance



## Why It Matters

- Apply the best practice consistently and keep the implementation focused.

## Apply When

- Laravel work that directly overlaps with this practice.

## Be Careful When

- Tasks outside this practice; use a more specific skill instead.

## Canonical Source

- Full best practice: https://github.com/Dutch-Laravel-Foundation/best-practices/blob/main/database-and-eloquent-orm/prevent-n-plus-one-queries/BEST_PRACTICE.md
- Dutch translation: https://github.com/Dutch-Laravel-Foundation/best-practices/blob/main/database-and-eloquent-orm/prevent-n-plus-one-queries/translations/nl.md

## Workflow

1. Inspect the user's Laravel code before recommending changes.
2. Identify the narrow rule from this best practice that applies to the task.
3. Prefer Laravel's built-in conventions and documented APIs over custom abstractions.
4. Keep examples focused on this practice; reference other skills or practices when the task crosses boundaries.
5. Verify code changes with the project's available tests, linters, static analysis, or framework checks.

## Review Checklist

- The recommendation is Laravel-specific and grounded in this practice.
- Code examples use realistic Laravel file names, class names, and method names.
- The advice avoids mixing unrelated architecture, deployment, security, or testing topics.
- Related practices are mentioned when useful, but not re-explained in full.
- Dutch output, when requested, keeps framework and API names intact.