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
- Laravel Eager Loading Documentatie
- Laravel
preventLazyLoadingDocumentatie - Laravel Counting Related Models
- Gebruik Chunking voor Grote Datasets
- Gebruik Eloquent Scopes en Casts
- Laravel Boost Best Practices PR
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.