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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 05:30:46