如何在Laravel中获取最后一条消息属于指定用户的会话列表
解决Laravel Eloquent获取最后一条消息属于指定用户的会话列表问题
首先确保模型间的关联关系配置正确:
- Conversation 模型:
class Conversation extends Model { public function messages() { return $this->hasMany(Message::class); } }
- Message 模型:
class Message extends Model { public function conversation() { return $this->belongsTo(Conversation::class); } public function user() { return $this->belongsTo(User::class); } }
下面提供三种可行的查询方案:
方案一:子查询匹配最新消息ID
先找出每个会话的最新消息ID,再筛选这些消息属于指定用户的会话:
$targetUserId = 1; $conversations = Conversation::whereIn('id', function ($query) use ($targetUserId) { // 先拿到所有会话的最新消息ID $latestMessageIds = function ($subquery) { $subquery->select(DB::raw('MAX(id)')) ->from('messages') ->groupBy('conversation_id'); }; // 筛选出这些最新消息中属于目标用户的会话ID $query->select('conversation_id') ->from('messages') ->where('user_id', $targetUserId) ->whereIn('id', $latestMessageIds); })->get();
方案二:利用withMax简化查询
Laravel的withMax方法可以快速获取每个会话的最新消息ID,再通过whereHas筛选归属用户:
$targetUserId = 1; $conversations = Conversation::withMax('messages', 'id') ->whereHas('messages', function ($query) use ($targetUserId) { // 匹配当前会话的最新消息,且该消息属于目标用户 $query->where('id', DB::raw('messages_max_id')) ->where('user_id', $targetUserId); }) ->get();
注:withMax会给每个Conversation实例新增messages_max_id属性,存储对应会话的最新消息ID。
方案三:whereExists子查询验证
直接查询存在“最后一条消息属于目标用户”的会话:
$targetUserId = 1; $conversations = Conversation::whereExists(function ($query) use ($targetUserId) { $query->select(DB::raw(1)) ->from('messages as m1') ->whereColumn('m1.conversation_id', 'conversations.id') ->where('m1.user_id', $targetUserId) // 确保当前消息是会话的最后一条(没有更大ID的消息) ->whereNotExists(function ($subquery) { $subquery->select(DB::raw(1)) ->from('messages as m2') ->whereColumn('m2.conversation_id', 'm1.conversation_id') ->where('m2.id', '>', 'm1.id'); }); })->get();
内容的提问来源于stack exchange,提问作者issdilshod
相关产品推荐
相关产品推荐

