Perform order by relationship field in Eloquent

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company
Title: Efficiently Perform Order by Relationship Fields in Eloquent

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

$query = Product::whereHas('variants')
        ->with('variants')
        ->with('reviews');

$query = $this->addOrderConstraints($request, $query);

$products = $query->paginate(20);
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:
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;
}
Note that we are using the with() method to eager load all related models instead of performing multiple database queries when retrieving the products.

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:
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')
To fix this, we need to apply the order constraints to each related model. We can achieve this with additional joins:
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;
}
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.

Conclusion

To perform order by relationship fields in Eloquent, we must use joins to explicitly define the desired order for each related model. By using custom methods and applying the correct constraints, you can achieve efficient and accurate filtering of data while maintaining a clean code base. Remember that it's always better to keep your database schema normalized and avoid storing redundant information in relationships when possible. This approach simplifies your application logic and ensures optimal performance from your database queries.