Skip to main content

Black Friday 2025! Only until December 1st: coupon FRIDAY25 for 40% off Yearly/Lifetime membership!

Read more here
Tutorial Free

Eloquent withWhereHas Method: Don't Repeat Conditions

March 03, 2023
2 min read

In Laravel, we have a method called whereHas that takes the parent Model only if it has a relationship matching a condition. As an example:

app/Http/Controllers/UserController.php

public function index()
{
$users = User::whereHas('posts', function ($query) {
$query->where('published', 1);
})
->get();
 
return view('users.index', compact('users'));
}

This code will return all users that have at least one published post. But we won't have posts loaded in the $users collection automatically. Let's fix that in two different ways that depend on your Laravel versions.


Before Laravel 9.17

The simplest way to fix it is to use the with() method:

app/Http/Controllers/UserController.php

public function index()
{
$users = User::whereHas('posts', function ($query) {
$query->where('published', 1);
})
->with('posts' => function($query) {
$query->where('published', 1);
})
->get();
 
return view('users.index', compact('users'));
}

We just filtered based on the relationship and loaded the filtered data. But the problem is that we have to write the condition twice.


New in Laravel 9.17

It is solved since Laravel 9.17 with the new withWhereHas() method that combines the whereHas() and with() functions. Let's see it in action:

app/Http/Controllers/UserController.php

public function index()
{
$users = User::withWhereHas('posts', function ($query) {
$query->where('published', 1);
})->get();
 
return view('users.index', compact('users'));
}

It will do the same as the previous code but without us repeating the condition twice in the code.

We solved a DRY problem and made our code more readable.

Enjoyed This Tutorial?

Get access to all premium tutorials, video and text courses, and exclusive Laravel resources. Join our community of 10,000+ developers.

Comments & Discussion

F
fpolli ✓ Link copied!

In a model relationship can you do something like this:

public function siteAvatar(): HasOne { return $this->HasOne(Avatar::class)->withWhereHas('sites', function (Builder $query) { $query->where('id', 100); }); }

We'd Love Your Feedback

Tell us what you like or what we can improve

Feel free to share anything you like or dislike about this page or the platform in general.