Building a query is just method chaining on the model. Nothing runs until you call a terminator (get, first, count, paginate).
Post::where('is_published', true)
->where('user_id', auth()->id())
->orderByDesc('created_at')
->paginate(20);
Eager loading (fix N+1)
Without eager loading, this is N+1:
foreach (Post::all() as $post) {
echo $post->author->name; // ← one query per row
}
With with():
Post::with('author')->get();
One join, one render, no extra queries.
Chunking for big tables
::all() materialises every row. For 100k+ rows use chunkById:
Post::chunkById(500, function ($posts) {
foreach ($posts as $post) processOne($post);
});
It paginates internally by primary key — safer than offset/limit because deletes during the iteration don't skip rows.