DEV Community

Cover image for Stop Misusing Eloquent: get() vs all() - When to Use Which (and Why)
Tahsin Abrar
Tahsin Abrar

Posted on

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

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

$reviews = Review::with('reviewDocuments')->get();
Enter fullscreen mode Exit fullscreen mode

Looks fine, right? But what about this?

$reviews = Review::all();
Enter fullscreen mode Exit fullscreen mode

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'); 
Enter fullscreen mode Exit fullscreen mode

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();
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Using get()

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

Eager loading

$reviews = Review::with('reviewDocuments')->get();
Enter fullscreen mode Exit fullscreen mode

👉 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());
Enter fullscreen mode Exit fullscreen mode

Real-life example: Reviews and documents

Suppose you want all reviews with their documents:

$reviews = Review::with('reviewDocuments')->get();
Enter fullscreen mode Exit fullscreen mode

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();
Enter fullscreen mode Exit fullscreen mode

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

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');
Enter fullscreen mode Exit fullscreen mode

After

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

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()

Top comments (0)