I have 2 tables for a chatting system
"users" table structure:
id | name |
---|
"messages" table structure:
id | sender_id | receiver_id | message |
---|
I want to return friend users ordered by when there was chatting between you and friend last time.
Note: id
works same as timestamp
Suppose,
id | sender_id | receiver_id | message |
---|---|---|---|
1 | $userA->id |
$userB->id |
abc |
2 | $userC->id |
$userA->id |
xyz |
So, If $userA
is the logged in user - I want users to be returned like:
[
0 => $userC,
1 => $userB,
2 => $userD,
3 => $userE,
4 => $userF,
...
]
(where $userD
, $userE
, $userF
has no messages with user $userA
)
Basically I want to return all the friend users sorted using if user has any message with logged in user.
My current code giving me some unexpected result -
return DB::table('users')->leftJoin('messages', function ($join) {
$join->on('users.id', '=', 'messages.sender_id')
->where('messages.sender_id', auth()->id())
->orOn('users.id', '=', 'messages.receiver_id')
->where('messages.receiver_id', auth()->id());
})
->select('users.*')
->where('users.id', '!=', auth()->id())
->orderBy('messages.id', 'asc')
->get();
Honestly I can't be sure if this will work as I can't testi it, but I think code should be something like:
$messagesSent = DB::table('messages')
->select('sender_id as other_user', DB::raw('MAX(id) as last_message_id'))
->where('receiver_id', auth()->id())
->groupBy('sender_id');
$messagesSentOrReceived = DB::table('messages')
->select('receiver_id as other_user', DB::raw('MAX(id) as last_message_id'))
->where('sender_id', auth()->id())
->groupBy('receiver_id')
->union($messagesSent);
$usersWithCommunication = DB::table('users')
->select('other_user', DB::raw('MAX(last_message_id) as last_message_id'))
->joinSub($messagesSentOrReceived, 'latest_messages', function ($join) {
$join->on('users.id', '=', 'latest_messages.other_user');
})
->groupBy('other_user');
return DB::table('users')
->leftJoinSub($usersWithCommunication, 'latest_communications', function ($join) {
$join->on('users.id', '=', 'latest_communications.other_user');
})
->select('users.*')
->orderBy('latest_communications.last_message_id', 'asc')
->get();