在 Laravel 中获取每个用户的最新邮件(行)

2022-08-30 23:38:43

TL;DR:需要来自每个发件人的最新消息。

在我的Laravel应用程序中,我有两个表:

用户:

  • 编号
  • 名字

消息:

  • 编号
  • sender_id
  • recipient_id
  • 身体
  • created_at

当然还有模型。

用户型号:

public function messages() {
    return $this->hasMany('App\Message', 'recipient_id');
}

消息模型:

public function sender() {
    return $this->belongsTo('App\User', 'sender_id');
}

public function recipient() {
    return $this->belongsTo('App\User', 'recipient_id');
}

当用户打开收件箱时,他应该会看到来自任何其他用户的最新邮件列表。

因此,如果有消息:

id sender_id recipient_id body created_at
1, 2,        1,           hi,  2016-06-20 12:00:00
2, 2,        1,           hi,  2016-06-21 12:00:00
3, 3,        1,           hi,  2016-06-20 12:00:00
4, 3,        1,           hi,  2016-06-21 12:00:00

然后,ID 为 1 (recipient_id) 的用户应仅看到 ID 为 2 和 4 的消息。

这是用户模型中的当前解决方案:

return Message::whereIn('id', function($query) {
                $query->selectRaw('max(`id`)')
                ->from('messages')
                ->where('recipient_id', '=', $this->id)
                ->groupBy('sender_id');
            })->select('sender_id', 'body', 'created_at')
            ->orderBy('created_at', 'desc')
            ->get();

这是有效的,但是如果有可能以Laravel的方式实现这一目标,我就在徘徊。可能是急切加载。我的Laravel技能还不够,经过几天的尝试,我没有解决方案。

谢谢。


答案 1

这篇文章中汲取灵感,最有效的方法是这样的:

DB::table('messages AS m1')
    ->leftjoin('messages AS m2', function($join) {
        $join->on('m1.sender_id', '=', 'm2.sender_id');
        $join->on('m1.id', '<', 'm2.id')
    })->whereNull('m2.id')
    ->select('m1.sender_id', 'm1.body', 'm1.created_at')
    ->orderBy('m1.created_at', 'm1.desc')->get();

虽然它不是最友好的Laravel,但它是基于性能的最佳解决方案,正如上面这个答案中链接的帖子所强调的那样。


答案 2

为什么不像这样简单地访问 , -messages

// get the authenticated user
$user = \Auth::user(); 

// find the messages for that user
return User::with('message')->find($user->id)->messages;

推荐