Laravel - счетчик непрочитанных сообщений

Есть подобие чата, в который могут писать сообщения все зарегистрированные юзеры.

       Schema::create('messages', function (Blueprint $table) {
           $table->increments('id');
           $table->integer('user_id')->unsigned();
           $table->integer('group_id')->unsigned();
           $table->text('message');
           $table->timestamps();
       });

нужно реализовать счетчик непрочитанных сообщений для каждого юзера. Допустим пока юзер отсутствовал, в чат написали 10 новых сообщений, нужно для каждого юзера отобразить количество непрочитанных сообщений (для каждого юзера оно будет свое).

Когда юзер открывает сообщения, они будут помечаться как прочитанные (прочитаны этим конкретным юзером)

сделал таблицу в которой буду хранить даты прочтения для каждого юзера

        Schema::create('message_read_date', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('user_id');
            $table->integer('message_id');
            $table->timestamp('read_at')->nullable();
            $table->unique(['user_id', 'message_id']);
        });

И тут застрял, как мне потом показать юзеру сколько у него непрочитанных сообщений. Может делаю что то не так?


Ответы (1 шт):

Автор решения: countto25

Нужны отношения у моделей. Так как речь идет, судя по всему, о групповых чатах - оптимально сделать это через BelongsToMany. И при этом использовать данные из таблицы-посредника о прочтении

    Schema::create('user_messages', function (Blueprint $table) {
        $table->foreignId('user_id')->references('id')->on('users');
        $table->foreignId('message_id')->references('id')-on('messages');
        $table->timestamp('read_at')->nullable()->default(null);
        $table->unique(['user_id', 'message_id']);
    });

Когда создается сообщение в группе, через события моделей создавать еще и ассоциацию с юзерами, которые находятся в группе. После этого в модели пользователя можно получить непрочитанные сообщения через пивот, создав для них отдельный метод:

class User extends Model {
   ...
   public function unreadMessages(): BelongsToMany 
   {
       return $this->belongsToMany(Message::class)->wherePivot('read_at', null);
   }
}

Остается только рассортировать данные на фронтенде, поработав с коллекциями сопоставить сообщения с чатами, чтобы отрисовать нужный бейдж. И в случае прочтения - обновлять пивот.

→ Ссылка