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

Laravel聊天系统开发:用户会话列表查询方案求助

聊天系统会话列表查询实现问题

数据库表结构

users表

idnameavatar
1name1/img/avatar/1.jpg
2name2/img/avatar/2.jpg
3name3/img/avatar/3.jpg

user_messages表

idmessage_idsender_idreceiver_idcreated_at
11132022-12-13 19:34:11
22312022-12-13 19:35:00
33122022-12-14 16:28:00
44122022-12-15 09:39:00
55232022-12-15 10:01:00

messages表

idmessage
1hello
2hello
3hello
4how are you
5hi

需求

获取user1的聊天列表,展示其与user2、user3的会话,每条会话需包含:

  • 对方姓名
  • 对方头像
  • 最后一条消息内容
  • 最后一条消息发送时间

现有模型代码

UserMessage 模型

class UserMessage extends Model
{
    public function message(){
        return $this->belongsTo(Message::class);
    }
}

Message 模型

class Message extends Model
{
    public function user_messages(){
        return $this->hasMany(UserMessage::class);
    }

    public function users(){
        return $this->belongsToMany(User::class, 'user_messages', 'message_id', 'sender_id')->withTimestamps();
    }
}

可行实现方案(来自zohrehda)

以下代码可满足需求:

$messages = UserMessage::
            where('receiver_id', $user_id)
            ->orWhere('sender_id', $user_id)
            ->leftJoin('messages', 'user_messages.message_id', 'messages.id')
            ->select('user_messages.*', 'messages.message')
            ->get();

$chat_list = [];
foreach($messages as $message){
    if($message->receiver_id != $user_id)
    {
        $chat_list[$message->receiver_id][] = $message;
    }
    elseif($message->sender_id != $user_id)
    {
        $chat_list[$message->sender_id][] = $message;
    }
}

$array = [];
foreach($chat_list as $user_id => $messages)
{
    $user = User::find($user_id);
    $array[] = [
        'user_name' => $user->name,
        'user_avatar' => $user->avatar,
        'last_message' => last($messages)->message,
        'created_at' => last($messages)->created_at
    ];
}

代码逻辑说明

  1. 查询当前用户所有参与的消息记录(作为发送方或接收方),通过左连接messages表获取消息内容
  2. 将消息按对方用户ID分组,把同一用户的所有消息归为一组
  3. 遍历每个分组,查询对方用户的姓名和头像,提取该组最后一条消息的内容及发送时间,整理成需求格式的数组

性能优化建议

原方案中每次循环调用User::find($user_id)会产生N+1查询问题,可通过预加载用户数据优化:

// 收集所有会话对方的用户ID
$userIds = array_keys($chat_list);
// 批量查询用户并按ID索引
$users = User::whereIn('id', $userIds)->get()->keyBy('id');

$array = [];
foreach($chat_list as $user_id => $messages)
{
    $user = $users[$user_id];
    $array[] = [
        'user_name' => $user->name,
        'user_avatar' => $user->avatar,
        'last_message' => last($messages)->message,
        'created_at' => last($messages)->created_at
    ];
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 15:20:29