Laravel Eloquent, select only rows where the relation exists
Stefan Bogdanescu
Founder & Senior Architect · 2026-06-29
# Laravel Eloquent: Selecting Only Rows Where a Relation Exists
As developers working with relational databases through an ORM like Eloquent, one of the most common tasks is filtering results based on whether related records exist. You don't just want to load all users; you only want the users who actually have comments, or posts, or any other defined relationship. This requirement moves beyond simple eager loading and requires leveraging the power of the query builder.
This post will walk you through the correct and most efficient way to select Eloquent models based on the existence of their relationships, using best practices that keep your queries fast and readable.
## The Challenge: Filtering by Relationship Existence
The core question is: How do I tell Eloquent to only return `User` models that have at least one associated `Comment`?
A naive approach might involve loading all users and then filtering them in PHP, which forces the database to retrieve far more data than necessary. We need a solution that pushes this filtering logic down into the SQL query itself.
## The Eloquent Solution: Using `whereHas()`
The correct tool for this job in Laravel is the `whereHas()` method. This method allows you to constrain your main query based on the existence of related models. It translates directly into an efficient SQL `JOIN` or `EXISTS` clause, ensuring that only relevant parent records are retrieved from the database.
If you have a `User` model and a `comments` relationship defined:
```php
// In your User Model:
public function comments()
{
return $this->hasMany(Comment::class);
}
```
You can now filter for users who have comments like this:
```php
$usersWithComments = User::whereHas('comments')
->orderBy('id')
->paginate(20);
```
### How `whereHas()` Works Under the Hood
When you call `User::whereHas('comments')`, Eloquent constructs a query that essentially asks the database: "Select all users where there exists at least one matching record in the related `comments` table." This is vastly more efficient than fetching every user and then checking each one individually in application memory.
This technique is fundamental to writing performant queries in Laravel. For more advanced relationship checks, you can also use `whereHas` with constraints on the related model itself:
```php
// Select users who have comments AND where those comments are published
$publishedUsers = User::whereHas('comments', function ($query) {
$query->where('is_published', true);
})->get();
```
This demonstrates how powerful Eloquent is at abstracting complex SQL operations into clean, expressive PHP methods. As you build complex data interactions in Laravel, understanding these foundational query methods is key to writing scalable applications. For deeper insights into building robust database interactions, exploring the official documentation on [laravelcompany.com](https://laravelcompany.com) is highly recommended.
## Filtering vs. Eager Loading: Understanding the Difference
It is crucial to distinguish between filtering relationships and eager loading them. These serve different purposes:
1. **Filtering (`whereHas()`):** Used to **restrict** the main query results based on relationship existence. This modifies *which* parent records are returned from the database.
2. **Eager Loading (`with()`):** Used to **load** the related data along with the main models in a subsequent step (usually via `JOIN` or separate queries).
You often use both together: you filter first to get the correct set of parents, and then eager load them to fetch their children efficiently.
### Example Combining Filtering and Loading
Here is how you would retrieve the 20 users who have comments, and then eagerly load those comments for each user:
```php
$users = User::whereHas('comments') // Step 1: Filter down to only users with comments
->with('comments') // Step 2: Eager load the comments for those filtered users
->orderBy('id')
->paginate(20);
// $users now contains the paginated results, and each user object
// will have its 'comments' relationship loaded.
```
## Conclusion
By mastering methods like `whereHas()`, you unlock Laravelâs potential to write highly optimized database queries. Instead of relying on slow, application-side filtering, you instruct Eloquent to handle the heavy lifting directly in SQL. Using these techniques ensures that your application remains fast, scalable, and adheres to the principles of clean, efficient coding practices championed by the Laravel ecosystem.