查询用户在聊天中的未读消息

Query unread Messages by a User in a Chat

我正在尝试构建一个越来越难的查询... 我正在 Laravel 中开发一个具有简单结构的聊天应用程序:

所以

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 消息来实现此目的?或者我可以做这样的操作:

但我不知道如何 '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);
        });
    });
}

呸,好难啊

希望对其他人有所帮助!

请记住,所有这些都可以通过一个查询来完成 ;)