Stop Misusing Eloquent: get() vs all() – When to Use Which (and Why)



This content originally appeared on DEV Community and was authored by Tahsin Abrar

If you’ve been using Laravel for a while, chances are you’ve run into this situation:

$reviews = Review::with('reviewDocuments')->get();

Looks fine, right? But what about this?

$reviews = Review::all();

Both give you collections of records, but they are not the same thing. Knowing when to use get() vs all() can save your app from slow queries, memory bloat, and unhappy users.

A quick story from real life

A few years back, one of my teammates wrote this:

$users = User::all(); 
$active = $users->where('status', 'active'); 

It worked in testing. But in production, the users table had over a million rows. The server quickly ran out of memory, requests got painfully slow, and logs exploded with errors.

The fix was simple:

$active = User::where('status', 'active')->get();

Same result for the user. Huge performance improvement for the server.

Lesson learned: always let the database do the heavy lifting. That’s what it’s built for.

The mental model

  • Model::all()
    Runs a query with no constraints. Always fetches every single row from the table.

  • ->get()
    Runs the query you built, with where, orderBy, with, select, etc. It executes your constraints and gives you a collection of matching rows.

Syntax examples

Using all()

$reviews = Review::all(); // SELECT * FROM reviews

Using get()

$reviews = Review::where('status', 'active')
    ->orderBy('created_at', 'desc')
    ->get();

Eager loading

$reviews = Review::with('reviewDocuments')->get();

👉 Important: all() cannot be combined with with(), where(), or other query builder methods. It always returns everything.

Which is more optimized?

Short answer: get() is almost always better.

  • Database filters before sending data You only fetch the rows you need.
  • Uses indexes Your WHERE and ORDER BY statements leverage database indexes.
  • Reduces memory usage Less data transferred = less memory used in PHP.

So when is all() fine?

  • For tiny lookup tables like roles, countries, or categories.
  • When you cache the results permanently (like Cache::rememberForever).

Example:

$roles = Cache::rememberForever('roles', fn () => Role::all());

Real-life example: Reviews and documents

Suppose you want all reviews with their documents:

$reviews = Review::with('reviewDocuments')->get();

That’s good. But if you only want active reviews and specific fields:

$reviews = Review::query()
    ->select(['id', 'title', 'rating', 'status'])
    ->with(['reviewDocuments:id,review_id,path'])
    ->where('status', 'active')
    ->orderByDesc('created_at')
    ->get();

This avoids unnecessary data and keeps queries fast.

When to use which

Use all() when:

  • The table is small (dozens or a few hundred rows).
  • You need absolutely every record.
  • You plan to cache the result.

Use get() when:

  • You have filters (where, orderBy, limit, etc.).
  • You want eager loading (with()).
  • The table can grow large in production.
  • You want to select only certain columns.

Best practices

  1. Filter in SQL, not PHP
   // ❌ Bad
   $users = User::all()->where('active', true);

   // ✅ Good
   $users = User::where('active', true)->get();
  1. Paginate results for the UI
   $users = User::where('active', true)->paginate(20);
  1. Process large datasets in chunks
   User::where('active', true)
       ->chunk(1000, function ($users) {
           // process batch
       });
  1. Select only the columns you need
   Post::select('id', 'title')->get();
  1. Always eager load relationships
   $posts = Post::with('author')->get();
  1. Use aggregates for counts and sums
   $count = Order::where('status', 'pending')->count();
   $sum   = Order::where('paid', true)->sum('total');
  1. Use first(), find(), or exists() when appropriate
   $user = User::find($id); 
   $exists = Order::where('status', 'pending')->exists();

Common mistakes to avoid

  • Using all() and then filtering with collection methods (where, filter).
  • Trying Model::with(...)->all(). This doesn’t work.
  • Fetching all columns including large text or json fields when you don’t need them.
  • Forgetting to eager load, leading to N+1 query issues.

Step-by-step migration from all() to get()

Before

$reviews = Review::all();
$active = $reviews->where('status', 'active');

After

$active = Review::where('status', 'active')
    ->with('reviewDocuments')
    ->orderByDesc('created_at')
    ->paginate(20);

Much faster, memory-friendly, and production-ready.

Quick reference

Use case Method
Get everything (tiny table only) Model::all()
Get filtered records ->where(...)->get()
Get one row (by condition) ->first() / ->firstOrFail()
Get by primary key ::find($id)
Paginate results ->paginate($perPage)
Process large datasets ->chunk($n) / ->cursor()
Only certain columns ->select([...])->get()
Aggregate results ->count(), ->sum(), ->exists()
With relationships ->with([...])->get()


This content originally appeared on DEV Community and was authored by Tahsin Abrar