Order By before Group By using Eloquent (Laravel)

Stefan Izdrail

Founder & Senior Architect · 2026-06-29

Laravel Company
Title: Order By before Group By using Eloquent (Laravel) Body: Ordering and grouping database records can often be a complex task, especially when dealing with large datasets, intricate relationships, or specific ordering rules. In this blog post, we'll focus on using Laravel's Eloquent ORM to order messages by their "createdAt" date before querying and grouping them by the unique "fromId". Our table structure provides us with essential information about the messages and their relationship:
CREATE TABLE `messages` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `fromId` int(11) NOT NULL,
  `toId` int(11) NOT NULL,
  `message` text NOT NULL,
  `status` int(11) NOT NULL,
  `device` varchar(100) NOT NULL,
  `createdAt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=57 DEFAULT CHARSET=latin1;
We want to get all messages where 'toId' = $id and group them by the sender ID ('fromId'). To achieve this, we need to order them using 'createdAt', which will ensure that the most recent message is displayed first. Here's the given query:
$chats = Message::with('sender','recipient')
        ->where('toId',$id)
        ->orderBy('createdAt')
        ->groupBy('fromId')
        ->paginate(10)
However, this query seems to be a bit off. The problem occurs because the order is applied after grouping, resulting in ordering within each group instead of the entire set of messages. To solve this issue, we need to implement the "Order By" before "Group By". Here's how you can perform that operation using Eloquent:
$chats = Message::with('sender','recipient')
        ->orderBy('createdAt')
        ->whereHas('recipient', function($query) use ($id) {
            $query->where('toId',$id);
          })
        ->groupBy('fromId')
        ->paginate(10)
This modified query ensures that the messages are ordered by their "createdAt" date before being grouped. Here's a breakdown: - `orderBy('createdAt')` orders the messages chronologically based on the 'createdAt' timestamp. - `whereHas('recipient', function($query) use ($id) {` allows us to retrieve all messages that belong to the given recipient ID while preserving the original order, which would otherwise be lost when using the "where" method. - `$query->where('toId', $id);` restricts the query to include only those records where 'toId' equals our supplied identifier. - Finally, we wrap both conditions within a closure and use the "whereHas" method to apply this constraint on our relationship. This ensures that the order is not lost during grouping. In conclusion, by ordering messages by their creation date before grouping them based on the sender ID, you can ensure that the latest message from each sender is displayed first. The revised query demonstrates how we can achieve this using Eloquent effectively and maintain chronological order when working with groups of related data in a Laravel application.