You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel Eloquent按最新唯一条目排序:私信收件箱排序问题

Fixing Contact Sort by Latest Message in Laravel Inbox

Hey there! Let's get that contact list sorted correctly so your users see their most recent conversations at the top. The issue with your current code is that you're sorting messages in ascending order first, then deduplicating—which means you're keeping the oldest message from each sender instead of the newest one. Here's how to fix it:

Why Your Current Code Isn't Working

Let's break down your original code:

$messages = collect(Message::where('recipient_id', $user)->orderBy('created_at', 'desc')->get()); 
$messagesUnique = $messages->sortBy('created_at')->unique('sender_id'); 
$messagesUnique->values()->all();
  1. You first fetch messages sorted newest to oldest—good start!
  2. But then you re-sort them ascending (oldest to newest) before calling unique(). This means unique('sender_id') keeps the first occurrence of each sender, which is their oldest message.
  3. The final list ends up sorted by old messages, which is the opposite of what you want.

Handling this at the database level is more efficient, especially as your message count grows. We'll group messages by sender and grab the latest timestamp for each, then sort by that timestamp.

$userId = auth()->id(); // Replace with your authenticated user ID variable

// Get each sender's latest message timestamp
$latestMessageData = Message::where('recipient_id', $userId)
    ->select('sender_id', \DB::raw('MAX(created_at) as latest_message_at'))
    ->groupBy('sender_id')
    ->orderBy('latest_message_at', 'desc')
    ->get();

// If you need to load the full User models for contacts:
$contacts = User::whereIn('id', $latestMessageData->pluck('sender_id'))
    ->get()
    // Attach the latest message timestamp to each user
    ->map(function ($user) use ($latestMessageData) {
        $user->latest_message_at = $latestMessageData
            ->where('sender_id', $user->id)
            ->first()
            ->latest_message_at;
        return $user;
    })
    // Sort again to ensure correct order (in case User::get() changes the order)
    ->sortByDesc('latest_message_at');

Solution 2: Collection-Level Fix (Quick Adjustment)

If you prefer working with collections, just reverse the order of operations: sort newest to first, then deduplicate (so you keep the latest message per sender), and you're done.

$user = auth()->id(); // Replace with your user ID variable

// Fetch messages sorted newest to oldest first
$messages = Message::where('recipient_id', $user)->orderBy('created_at', 'desc')->get();

// Deduplicate by sender_id—since we're sorted newest first, this keeps the latest message per sender
$uniqueMessages = $messages->unique('sender_id');

// The list is already in the correct order, but we can explicitly sort to be safe
$sortedContacts = $uniqueMessages->sortByDesc('created_at')->values()->all();

Bonus: Handling Bidirectional Conversations

If your inbox should include conversations where the user was the sender (not just the recipient), adjust the query to include both cases, then deduplicate based on the other user's ID:

$userId = auth()->id();

$messages = Message::where(function ($query) use ($userId) {
    $query->where('recipient_id', $userId)
          ->orWhere('sender_id', $userId);
})->orderBy('created_at', 'desc')->get();

// Deduplicate by the other participant's ID
$uniqueContacts = $messages->unique(function ($message) use ($userId) {
    return $message->sender_id === $userId ? $message->recipient_id : $message->sender_id;
})->sortByDesc('created_at')->values()->all();

Either approach will get your contact list showing the most recent conversations at the top. The database method is better for large datasets, while the collection method is simpler for smaller apps.

内容的提问来源于stack exchange,提问作者Gazz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:49:12