Reader Stacks

Laravel Eloquent Where Clauses and Query Filtering: A Complete Reference

The where-family methods cover most of what you need to filter Eloquent queries — this reference covers the syntax for each variant in one place.

Eloquent's query builder offers a whole family of where-style methods, and knowing which variant to reach for avoids writing more verbose raw SQL or chaining conditions less clearly than necessary.

Multiple where conditions

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

Chained where() calls are combined with AND by default — each call narrows the result set further.

orWhere

$users = User::where('status', 'active')
    ->orWhere('role', 'admin')
    ->get();

Mixing where and orWhere without grouping can produce unexpected precedence — wrap the or logic in a closure when combining it with other conditions: where('status', 'active')->where(fn ($q) => $q->where('role', 'admin')->orWhere('role', 'editor')).

whereNull and whereNotNull

$unverified = User::whereNull('email_verified_at')->get();
$verified = User::whereNotNull('email_verified_at')->get();

whereIn and whereNotIn

$users = User::whereIn('id', [1, 2, 3])->get();
$users = User::whereNotIn('status', ['banned', 'suspended'])->get();

These accept an array directly, or a subquery closure for filtering against another table's results without a manual join.

orderBy and multiple orderBy calls

$users = User::orderBy('created_at', 'desc')->get();

$users = User::orderBy('last_name')
    ->orderBy('first_name')
    ->get();

Chaining multiple orderBy() calls sorts by the first column, then breaks ties using the next — useful for sorting a list alphabetically by last name, then first name.

limit (and its alias, take)

$topFive = Post::orderBy('views', 'desc')->limit(5)->get();
// equivalent
$topFive = Post::orderBy('views', 'desc')->take(5)->get();

groupBy

$counts = Order::select('status', DB::raw('count(*) as total'))
    ->groupBy('status')
    ->get();

having

$popularCategories = Category::withCount('posts')
    ->having('posts_count', '>', 10)
    ->get();

having() filters on the result of an aggregate (like a groupBy count), which is why it can't be replaced with a regular where() — the database evaluates having after grouping, and where before.

Combining these methods in practice

Most real queries chain several of these together — filtering with where/whereIn, sorting with orderBy, and paginating or limiting the result — and Eloquent's fluent syntax lets all of it read top-to-bottom in the order the database will actually apply it.