OrderBy on Eloquent whereHas relationship
Stefan Bogdanescu
Founder & Senior Architect · 2026-06-29
Mastering OrderBy on Eloquent Relationships: The whereHas Conundrum
As senior developers working with Laravel and Eloquent, we often deal with complex data relationships. Filtering based on related models using methods like whereHas is incredibly powerful for querying nested data. However, when we try to extend these filters to dictate the ordering of the primary results, we frequently run into subtle but frustrating issues.
Today, we are addressing a common challenge: how do you order your parent records (like Countys) based on an attribute from a filtered child relationship (like Items) when using Eloquent’s whereHas?
The Scenario: Filtering and Ordering Nested Data
Imagine you have a County model that has a one-to-many relationship with an Item model. You only want to retrieve counties that have at least one associated item marked as approved. Furthermore, you want these resulting counties to be listed alphabetically based on the names of those approved items.
Your initial attempt looks like this:
$counties = County::whereHas('items', function ($query) {
$query->where('approved', 1);
})->orderBy('name') // Attempting to order by a county field? (The issue is here)
->get();
As you correctly observed, while whereHas successfully filters the counties based on the existence of an approved item, applying orderBy() directly to the main query often defaults back to ordering by the primary key (id) unless the relationship constraint itself dictates the sorting context.
Why the Initial Approach Fails
The reason your attempt doesn't work as expected is that whereHas primarily constructs a subquery or an INNER JOIN structure designed for existence checks and filtering, not necessarily for defining the primary sort order of the parent model directly based on the joined relationship fields in a clean way. When you chain orderBy('name'), Eloquent prioritizes sorting the results of the main query (County) by its own columns, ignoring the context imposed by the nested filter unless explicitly handled.
To successfully order the parent based on a related attribute, we need to ensure that the relationship constraint itself is integrated into the ordering mechanism. We need to move beyond simple filtering and leverage explicit joins or more advanced constrained queries.
The Correct Solution: Leveraging Joins for Ordering
The most reliable and performant way to achieve this requirement is often by explicitly joining the related table and then applying both the filtering and the ordering constraints together. While whereHas is excellent for existence checks, when ordering based on relationship data, a direct join provides the necessary context for sorting.
Here is the recommended approach using an explicit join:
$counties = County::join('items', 'counties.id', '=', 'items.county_id')
->where('items.approved', 1) // Filter condition applied directly to the joined table
->select('counties.*') // Select only the county columns
->orderBy('items.name') // Order the counties by the item's name
->distinct() // Use distinct to prevent duplicate counties if multiple items match
->get();
Deeper Dive into the Technique
In this revised approach, we perform an explicit JOIN between the counties table and the items table. This brings all the necessary data into a single result set where we can apply both filtering (where) and sorting (orderBy) simultaneously.
join('items', 'counties.id', '=', 'items.county_id'): We establish the link between the parent and child tables.where('items.approved', 1): This filters the joined results, ensuring we only consider counties linked to approved items.orderBy('items.name'): Crucially, we now order the resulting set of counties based on thenamecolumn from the relateditemstable.distinct(): Since a county might have multiple approved items, usingdistinct()ensures that each county is listed only once, providing a clean list ordered by its associated item names.
This method gives you direct control over the join context, which is essential when mixing filtering and ordering across relationships—a concept foundational to efficient data retrieval in Laravel applications. For further insights into optimizing your database interactions with Eloquent, exploring advanced query building techniques, as detailed on platforms like Laravel Company, is highly recommended.
Conclusion
While whereHas remains indispensable for checking the existence of relationships, when you need to use the data from that relationship (like names) to dictate the primary order of your parent collection, switching to an explicit join operation often provides the most robust and clear solution. By mastering how Eloquent translates these constraints into SQL joins, you unlock powerful ways to query complex relational data efficiently.