Perform order by relationship field in Eloquent
Stefan Bogdanescu
Founder & Senior Architect · 2026-06-29
Title: Efficiently Perform Order by Relationship Fields in Eloquent
In this example, we begin by retrieving all related models using a query builder. The product belongs to many variations and also has several reviews. To handle sorting or filtering based on relationships, we need to create custom methods for each sorting criteria. This is done with your own logic in the controller code, where you define specific order constraints based on the user's input:
Note that we are using the with() method to eager load all related models instead of performing multiple database queries when retrieving the products.
To fix this, we need to apply the order constraints to each related model. We can achieve this with additional joins:
In this example, we join the products table with both variations and reviews and apply order constraints separately. This ensures that each related model is ordered correctly while maintaining a clear application logic.
The world of modern web development is vast and ever‑changing. Among the popular frameworks, Laravel has gained a reputation for its simplicity, elasticity, and customization possibilities. One of the most important aspects of any application is how it handles and organizes data. This article will guide you through the process of creating a product filter using Eloquent ORM in Laravel, addressing an issue related to order by relationship fields during query execution.
The Code
php
$query = Product::whereHas('variants')
->with('variants')
->with('reviews');
$query = $this->addOrderConstraints($request, $query);
$products = $query->paginate(20);php
private function addOrderConstraints($request, $query) {
$order = $request->input('sort');
if ($order === 'new') {
$query->orderBy('products.created_at', 'DESC');
}
if ($order === 'price') {
$query->orderBy('variants.price', 'ASC');
}
return $query;
}Debugging Order Constraints
When testing these methods, you might encounter an error due to the order by relationship field. This happens because Eloquent performs a join query internally, and the order by clause is applied over the original table. For example:sql
select count(*) as aggregate from `products` where exists
(select * from `variants` where `products`.`id` = `variants`.`product_id`)
select * from `products` where exists
(select * from `variants` where `products`.`id` = `variants`.`product_id`)
select * from `variants` where `variants`.`product_id` in ('29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48')php
private function addOrderConstraints($request, $query) {
$order = $request->input('sort');
if ($order === 'new') {
$query->join('variants', function($join) {
$join->on('products.id', '=', 'variants.product_id');
})
->orderBy('variants.price', 'ASC')
->with('reviews')
->whereHas('reviews')
->orderBy('products.created_at', 'DESC');
}
if ($order === 'price') {
$query->join('variants', function($join) {
$join->on('products.id', '=', 'variants.product_id');
})
->orderBy('variants.price', 'ASC')
->with('reviews')
->whereHas('reviews');
}
return $query;
}