Eloquent::when(): No More if-elses for Conditional Queries

Tutorial last revisioned on August 10, 2022 with Laravel 9

For a while many of us used to write conditional queries with "if-else", something like this:

if (request('filter_by') == 'likes') {
    $query->where('likes', '>', request('likes_amount', 0));
}
if (request('filter_by') == 'date') {
    $query->orderBy('created_at', request('ordering_rule', 'desc'));
}

What if I told you there's a (much) better way? Easily readable and more Laravel-ish. Meet when() method.

$query = Author::query();

$query->when(request('filter_by') == 'likes', function ($q) {
    return $q->where('likes', '>', request('likes_amount', 0));
});
$query->when(request('filter_by') == 'date', function ($q) {
    return $q->orderBy('created_at', request('ordering_rule', 'desc'));
});

$authors = $query->get();

Looks nicer, doesn't it?


Notice: click here to watch video version of this lesson for free, in my 4-hour online-course Eloquent: Expert Level


Wait, there's more

In the example below we will filter users only if the role was passed as a request option.

This means - as long as there is no parameter or it's false/null - you will see all of the users but if it becomes a value, lets say "1" for administrator - you will only see administrators.

$query = User::query();

// From Laravel 5.4 you can pass the same condition value as a parameter
$query->when(request('role', false), function ($q, $role) {
    return $q->where('role_id', $role);
});

$authors = $query->get();

What about default values?

Bellow example shows third argument to the when method. This closure will only execute if the first argument evaluates as false.

Author::query();
->when(request('filter_by') == 'likes', function ($q) {
    return $q->where('likes', '>', request('likes_amount', 0));
}, function ($q) {
    return $q->orderBy('created_at', request('ordering_rule\, 'desc'));
})->get();

It's not just a prettier way to write the same "IF" but is also a great way to organize conditional queries.

More information about conditional queries: https://laravel.com/docs/master/queries#conditional-clauses

Here's a pull request for the parameter acceptance (not mentioned in official docs): https://github.com/laravel/framework/pull/18419

No comments or questions yet...

Like our articles?

Become a Premium Member for $129/year or $29/month
What else you will get:
  • 22 courses (477 lessons, total 38 h 20 min)
  • 2 long-form tutorials (one new every week)
  • access to project repositories
  • access to private Discord