Get latest message (row) per user in Laravel

后端 未结 9 1087
逝去的感伤
逝去的感伤 2021-02-19 01:37

TL;DR: Need latest message from each sender.

In my Laravel application I have two tables:

Users:

  • id
  • name

Messages:

相关标签:
9条回答
  • 2021-02-19 01:43

    I found this solution in another forum, I think that is what you were looking for. I post it so it can be useful for other users

            DB::select('
                SELECT t1.*
                FROM messages AS t1
                INNER JOIN
                (
                    SELECT
                        LEAST(sender_id, recipient_id) AS user_id,
                        GREATEST(sender_id, recipient_id) AS recipient_id,
                        MAX(id) AS max_id
                    FROM messages
                    GROUP BY
                        LEAST(sender_id, recipient_id),
                        GREATEST(sender_id, recipient_id)
                ) AS t2
                    ON LEAST(t1.sender_id, t1.recipient_id) = t2.sender_id AND
                       GREATEST(t1.sender_id, t1.recipient_id) = t2.recipient_id AND
                       t1.id = t2.max_id
                    WHERE t1.sender_id = ? OR t1.recipient_id = ?
                ', [auth()->guard('api')->user()->id, auth()->guard('api')->user()->id]);
    

    original post: https://laracasts.com/discuss/channels/laravel/get-the-latest-message-of-chat-model-with-mysql-just-cannot-get-the-idea-how-to-do-this?page=1#reply=392529

    0 讨论(0)
  • 2021-02-19 01:46

    Why not simply accessing the messages, like this -

    // get the authenticated user
    $user = \Auth::user(); 
    
    // find the messages for that user
    return User::with('message')->find($user->id)->messages;
    
    0 讨论(0)
  • 2021-02-19 01:48

    this may be a solution (not tested though)

    User::with([
    'messages' => function ($q) {
        $q->select('sender_id', 'body')->groupBy('sender_id')->orderBy('created_at', 'desc');
    }
    ])->find(1);
    
    0 讨论(0)
  • 2021-02-19 01:51

    I like a simpler approach which is mentioned here.

    In your User model additionally to existing messages() relationship, add this relationship

    public function latestMessage() 
    {
        return $this->hasOne(Message::class, 'recipient_id')->latest();
    }
    

    Then when you query simply query like this.

    $messages = User::with('latestMessage')->get();
    

    $messages contains latest message per user.

    Edit

    In order to order the result by datetime/id you could do it like this.

    $messages = User::with(['latestMessage' => function($message) {
        $message->orderBy('id', 'desc');
    }])->get();
    

    $messages contains latest message per user ordered by id. Refer this answer

    0 讨论(0)
  • 2021-02-19 01:51

    Maybe you can try this one:

            $user = \Auth::user(); 
    
            // Get the latest date
            $last_date_created = Message::latest()->first()->created_at; // also check for possible null
    
            // Get the date only - use to specify date range in the where section in the eloquent query
            $target_date = date('Y-m-d', strtotime( $last_date_created ) );
    
            // Retrieve the messages
            $latest_posts = Message::where('recipient_id', $user->id)
                                   ->where('created_at', '>=', $target_date . ' 00:00:00')
                                   ->where('created_at', '<=',  $target_date . ' 23:59:59')
                                   ->groupBy('sender_id')
                                   ->groupBy('created_at')
                                   ->get();
    
            return $latest_posts;
    

    This may not be very efficient since it took two queries to do the job but you will gain benefits thru code readability.

    I hope it works the way it should be. I haven't tested it though but that's how I usually do this... Cheers!

    0 讨论(0)
  • 2021-02-19 01:52

    You can try this one

    Messages::where('recipient_id',**{USER_ID}**)
              ->group_by('sender_id')
              ->order_by('id','desc')
              ->get();
    
    0 讨论(0)
提交回复
热议问题