Laravel聊天系统开发:用户会话列表查询方案求助
聊天系统会话列表查询实现问题
数据库表结构
users表
| id | name | avatar |
|---|---|---|
| 1 | name1 | /img/avatar/1.jpg |
| 2 | name2 | /img/avatar/2.jpg |
| 3 | name3 | /img/avatar/3.jpg |
user_messages表
| id | message_id | sender_id | receiver_id | created_at |
|---|---|---|---|---|
| 1 | 1 | 1 | 3 | 2022-12-13 19:34:11 |
| 2 | 2 | 3 | 1 | 2022-12-13 19:35:00 |
| 3 | 3 | 1 | 2 | 2022-12-14 16:28:00 |
| 4 | 4 | 1 | 2 | 2022-12-15 09:39:00 |
| 5 | 5 | 2 | 3 | 2022-12-15 10:01:00 |
messages表
| id | message |
|---|---|
| 1 | hello |
| 2 | hello |
| 3 | hello |
| 4 | how are you |
| 5 | hi |
需求
获取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 ]; }
代码逻辑说明
- 查询当前用户所有参与的消息记录(作为发送方或接收方),通过左连接
messages表获取消息内容 - 将消息按对方用户ID分组,把同一用户的所有消息归为一组
- 遍历每个分组,查询对方用户的姓名和头像,提取该组最后一条消息的内容及发送时间,整理成需求格式的数组
性能优化建议
原方案中每次循环调用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
相关产品推荐
相关产品推荐

