Eager Loading
debt(d5/e3/b5/t5)
Closest to 'specialist tool catches it' (d5). The detection_hints list laravel-debugbar, clockwork, and laravel-telescope — these are specialist profiling/debugging tools, not default linters or compiler checks. The N+1 pattern is silent in normal execution but visible when these tools are active, placing it squarely at d5.
Closest to 'simple parameterised fix' (e3). The quick_fix is adding ->with(['relation1','relation2']) to an existing Eloquent query — a small, localised change within one query or repository method. It's more than a one-line mechanical swap because you must identify all relationships needed and audit usage, but it doesn't span multiple files structurally, so e3 fits.
Closest to 'persistent productivity tax' (b5). The concept applies_to web, cli, and queue-worker contexts, meaning it's a recurring concern across the full PHP application surface. Every developer working on any data-fetching code must reason about eager vs. lazy loading decisions, and the common_mistakes list shows multiple dimensions of ongoing cost (over-loading, under-loading, nested relationships). It's a persistent tax on many work streams but doesn't fully define the system's shape, so b5.
Closest to 'notable trap — a documented gotcha most devs eventually learn' (t5). The misconception field states explicitly: 'Eager loading is always better than lazy loading' — a common overcorrection once developers learn about N+1. The trap is bidirectional: under-use causes N+1 problems, over-use wastes memory and query time. This is a well-documented gotcha that most developers encounter and learn, fitting t5.
Also Known As
TL;DR
Explanation
Eager loading fetches all needed data in one query (or a small fixed number), whereas lazy loading issues additional queries when related data is accessed. In PHP ORMs, eager loading is typically triggered with with() or join() methods. It is the remedy for N+1 query problems: instead of loading 100 posts and then issuing 100 separate queries for each post's author, eager loading fetches all authors in one additional query. The trade-off is fetching data that may not be needed — profile queries to find the right balance.
Common Misconception
Why It Matters
Common Mistakes
- Eager loading every relationship by default — loading unused related data wastes memory and query time.
- Not checking that eager loading is actually used — an eager-loaded relationship that's never accessed is pure waste.
- Eager loading deeply nested relationships unnecessarily — each level multiplies the data fetched.
- Using eager loading in APIs where the client only needs IDs — load just what the response requires.
Code Examples
// Triggers N+1 queries — one per order
$orders = Order::all();
foreach ($orders as $order) {
echo $order->user->name; // each access fires a new query
}
// Eager load — single JOIN query fetches all related records
$orders = Order::with('user')->get();
foreach ($orders as $order) {
echo $order->user->name; // no additional query
}
// Nested relationships:
$orders = Order::with(['user', 'items.product', 'shipment'])->get();
// Constrained eager loading:
$users = User::with(['orders' => fn($q) => $q->where('status', 'paid')->latest()])->get();
// Check for N+1 in development:
// Laravel Debugbar or:
DB::listen(fn($q) => logger($q->sql)); // logs every query