Challenge 3: Fix an N+1 Hiding Behind a Resource — Possible Solution ==================================================================== // The (unchanged) Resource — this class itself is NOT the problem // app/Http/Resources/BookResource.php class BookResource extends JsonResource { public function toArray(Request $request): array { return [ 'id' => $this->id, 'title' => $this->title, 'author_name' => $this->author->name, // direct relationship access ]; } } // BEFORE — the controller feeds the Resource an un-eager-loaded query // app/Http/Controllers/BookController.php public function index() { return BookResource::collection(Book::all()); // For N books, $this->author->name inside toArray() triggers // 1 query per book — the classic N+1 pattern, just now happening // "inside" a Resource instead of a raw foreach loop. } // AFTER — fix the QUERY, not the Resource public function index() { return BookResource::collection(Book::with('author')->get()); // BookResource's toArray() code is COMPLETELY UNCHANGED — // $this->author->name now reads from data already loaded in the // single eager-loading query, with zero extra queries per book. } WHY THE FIX BELONGS AT THE QUERY LEVEL ------------------------------------------- BookResource::toArray() has no idea whether the underlying query eager loaded author or not — it just accesses $this->author->name the same way regardless. Eloquent's relationship-access magic transparently handles BOTH cases (already loaded, or needs to lazy-load right now) with identical syntax, which is exactly what makes this bug easy to introduce and easy to miss: the Resource code looks correct in isolation, compiles fine, and even WORKS correctly — it's just doing far more database work than necessary. Because the Resource class has no visibility into how the model collection was originally queried, the only place the N+1 problem can actually be fixed is at the query itself — adding with('author') before the collection of Book models is ever handed to BookResource::collection(). This is the same lesson from Chapter 6 (the N+1 problem originates at the query, not wherever the relationship happens to be accessed) applied one layer further removed, now that a Resource class sits between the query and the final response. WHY THIS WORKS -------------- - The fix requires touching exactly one line — the controller's query — and zero lines inside BookResource, demonstrating that "the Resource formats what's there" really does mean the fix is entirely a data- fetching concern, not a formatting concern. - Verifying this fix in practice means checking the ACTUAL QUERY COUNT (e.g. via Laravel's query log, or a tool like Laravel Debugbar) before and after the change — confirming it drops from 1+N to a small, fixed number regardless of how many books exist, the same verification approach used for every other N+1 fix throughout this project.