Skip to main content
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.

Recent Courses on Laravel Daily

Laravel 13 Starter Kit Teams and Customizations

10 lessons
33 min

How to Build Laravel 13 API From Scratch

30 lessons
1 h 23 min

How to Structure Laravel 13 Projects

16 lessons
1 h 32 min read
fpolli avatar

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); }); }