查询用户在聊天中的未读消息
Query unread Messages by a User in a Chat
我正在尝试构建一个越来越难的查询...
我正在 Laravel 中开发一个具有简单结构的聊天应用程序:
- 一个聊天有很多消息。
- 每条消息都属于一个用户。
- n:m 在用户和消息之间保存已读消息。
所以
Chat.php
public function messages() {
return $this->hasMany(Message::class)
}
Message.php
public function user() {
return $this->belongsTo(User::class);
}
public function reads() {
return $this->belongsToMany(User::class, 'reads');
}
User.php
public function messages() {
return $this->hasMany(Message::class);
}
public function reads() {
return $this->belongsToMany(Message::class, 'reads');
}
嗯,现在我要下一个查询
Give me all Chats that has Messages unread by me (logged user)
意思是这样的:
Chat::whereDoesntHave('messages.reads', function (Builder $q) {
return $q->where('user_id', auth()->id());
});
但这行不通,因为如果 Chat 有一条消息被我阅读,它就会被忽略 :(
也许我可以通过仅限定聊天的 LAST 消息来实现此目的?或者我可以做这样的操作:
- 统计所有聊天消息
- 统计我阅读的所有聊天消息
- 做一个减法,如果不是0,考虑这个聊天:D
但我不知道如何 'operation' 和 Eloquent。
请帮忙。
谢谢!
首先提取您阅读过的所有聊天的id。
$pluckedId=Chat::has('messages.reads', function (Builder $q) {
return $q->where('user_id', auth()->id());
})->pluck('id');
然后申请
Chat::whereNotIn('id', $pluckedId )->get();
嗯,我终于找到了只获取聊天的最后一条消息并检查这条消息是否已被特定用户阅读的方法,使用查询生成器方法。
这里我post魔法作用域,使用子查询;)
public function scopeUnreadBy(Builder $builder, int $userId)
{
//First, look for Chats with Messages
return $builder->whereHas('messages', function (Builder $q) use ($userId) {
$q->select(['last_message' => function(\Illuminate\Database\Query\Builder $sub) {
// Then, take only last one Message
$sub->select('id')
->from('messages')
->where('chat_id', 'chats.id')
->latest()
->limit(1);
}])->whereDoesntHave('reads', function(Builder $q) use ($userId) {
// Finally, check that last one has not been read :D
return $q->where('user_id', $userId);
});
});
}
呸,好难啊
希望对其他人有所帮助!
请记住,所有这些都可以通过一个查询来完成 ;)
我正在尝试构建一个越来越难的查询... 我正在 Laravel 中开发一个具有简单结构的聊天应用程序:
- 一个聊天有很多消息。
- 每条消息都属于一个用户。
- n:m 在用户和消息之间保存已读消息。
所以
Chat.php
public function messages() {
return $this->hasMany(Message::class)
}
Message.php
public function user() {
return $this->belongsTo(User::class);
}
public function reads() {
return $this->belongsToMany(User::class, 'reads');
}
User.php
public function messages() {
return $this->hasMany(Message::class);
}
public function reads() {
return $this->belongsToMany(Message::class, 'reads');
}
嗯,现在我要下一个查询
Give me all Chats that has Messages unread by me (logged user)
意思是这样的:
Chat::whereDoesntHave('messages.reads', function (Builder $q) {
return $q->where('user_id', auth()->id());
});
但这行不通,因为如果 Chat 有一条消息被我阅读,它就会被忽略 :(
也许我可以通过仅限定聊天的 LAST 消息来实现此目的?或者我可以做这样的操作:
- 统计所有聊天消息
- 统计我阅读的所有聊天消息
- 做一个减法,如果不是0,考虑这个聊天:D
但我不知道如何 'operation' 和 Eloquent。
请帮忙。 谢谢!
首先提取您阅读过的所有聊天的id。
$pluckedId=Chat::has('messages.reads', function (Builder $q) {
return $q->where('user_id', auth()->id());
})->pluck('id');
然后申请
Chat::whereNotIn('id', $pluckedId )->get();
嗯,我终于找到了只获取聊天的最后一条消息并检查这条消息是否已被特定用户阅读的方法,使用查询生成器方法。
这里我post魔法作用域,使用子查询;)
public function scopeUnreadBy(Builder $builder, int $userId)
{
//First, look for Chats with Messages
return $builder->whereHas('messages', function (Builder $q) use ($userId) {
$q->select(['last_message' => function(\Illuminate\Database\Query\Builder $sub) {
// Then, take only last one Message
$sub->select('id')
->from('messages')
->where('chat_id', 'chats.id')
->latest()
->limit(1);
}])->whereDoesntHave('reads', function(Builder $q) use ($userId) {
// Finally, check that last one has not been read :D
return $q->where('user_id', $userId);
});
});
}
呸,好难啊
希望对其他人有所帮助!
请记住,所有这些都可以通过一个查询来完成 ;)