Perform order by relationship field in Eloquent
Stefan Bogdanescu
Founder & Senior Architect · 2026-06-29
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;
}