laravel eloquent sort by relationship

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company
Title: Sorting Eloquent Relationships in Laravel Using Channel-Reply Connections One of the most significant advantages of using Laravel's Eloquent ORM is the ease with which it allows you to establish relationships between your models. However, sorting these relationships based on one of the related models can occasionally be a challenge. In this post, we will explore how to sort Eloquent relationships in Laravel by ordering channels based on their channel's associated replies. To start, let's take a look at our models and relationships: 1. User model with a belongsToMany relationship with the Channel model. The user can participate in multiple channels. 2. Channel model has a hasMany relationship with the Reply model for its replies. Each channel can have multiple replies but in different orders, depending on their creation dates. 3. A Reply model has a foreign key relationship to identify which channel it belongs to (channel_id). Now let's analyze our code trial that led to unexpected results: ```php // User Model public function channels() { return $this->belongsToMany('App\Channel', 'channel_user') ->withPivot('is_approved') ->with(['replies']) // Trying to order by replies.created_at, but not working ->orderBy('replies.created_at'); } ``` The issue with this code is that the relationship is defined as belongsToMany and thus doesn't have an inherent ordering mechanism. Consequently, you cannot directly apply a default order by clause on these relationships. This code also tries to load the replies for each user-channel relation but doesn't explicitly tell Eloquent to sort them in any particular order. To achieve our desired output, we need to follow a different approach: 1. First, we modify the Channel model relationship by adding a sorting criteria based on its latest Reply's creation date (we can use 'latest()' function for this): ```php public function replies() { return $this->hasMany('App\Reply', 'channel_id') ->orderBy('created_at', 'desc') // Ordering by descending order of reply creation dates ->take(1); // Takes only the latest reply for each channel } ``` This relationship ensures that we get the latest reply from a specific channel, irrespective of which user's involvement is checked. Since each Channel model will now have an inherent ordering based on its associated replies, we can proceed with our User Model to join and order these relationships without affecting performance. 2. Next, update the user relationship code: ```php public function channels() { return $this->belongsToMany('App\Channel', 'channel_user') ->withPivot('is_approved') // Joining channels with their latest replies (ordered by descending order) ->join('replies', function($query) { $query->on('channels.id', '=', 'replies.channel_id'); }) ->groupBy('replies.channel_id') // Group channels by their replies' channel ids ->orderBy('created_at', 'desc'); // Order users based on created dates of joined channel's latest reply } ``` This revision adds a join, grouping and ordering strategy that combines the user-to-channel relationship with an ordering mechanism based on their respective channels' replies. This way, we can order the user's channels according to the latest reply creation dates without affecting the database performance. Conclusion: In this post, we explored how to sort Eloquent relationships in Laravel by utilizing available functions and techniques while maintaining optimal performance. By adopting an iterative approach, we were able to solve our initial issue of ordering user channels according to their channel's latest reply creation date. This solution can be extended to any similar scenarios where a relationship needs to be sorted based on another associated model.