消息通知系统记录

简介

Laravel 自带了一套消息通知系统,还支持多种通知频道,包括数据库、邮件、短信等。
此处我们详细说明数据库通知频道

创建通知类

Laravel 中一条通知就是一个类,(通常在 app/Notifications 文件里),命令如下:

php artisan make:notification TopicReplied

每个通知类都包含一个 via 方法 以及多个消息构造方法( 如toMail或toDatabase )
via() 决定了通知在哪个频道上发送,如在数据库作为通知:

public function via($notifiable)
{
    // 开启通知的频道
    return ['database'];
}

而toDatabase($notifiable)方法会返回一个数组将被转化为json格式并存储到 notifications 数据表中的data字段中。

数据库通知

数据库通知频道会在一张数据表里存储所有信息,包含了比如通知类型、JSON 格式数据等描述通知的信息。
可以查询此表的内容在应用界面上展示通知。

1.首先创建生成迁移表

php artisan notifications:table

会生成 database/migrations/{$timestamp}_create_notifications_table.php 迁移文件

2.生成数据表

php artisan migrate

3.记录未读通知

在users表中新增 notification_count 字段,用来跟踪用户有多少通知

php artisan make:migration add_notification_count_to_users_table --table=users

打开生成的文件,修改如下:

public function up()
{
    Schema::table('users', function (Blueprint $table) {
        $table->integer('notification_count')->unsigned()->default(0);
    });
}

public function down()
{
    Schema::table('users', function (Blueprint $table) {
        $table->dropColumn('notification_count');
    });
}

应用数据库修改

php artisan migrate

发送通知

1.读取通知说明

在User模型类使用了Notifiable trait,而Notifiable中又引入了 HasDatabaseNotifications trait。
HasDatabaseNotifications中有3个函数,分别是 获取所有通知、获取未读通知 和 已读通知。

trait HasDatabaseNotifications
{
    public function notifications()
    {
        return $this->morphMany(DatabaseNotification::class, 'notifiable')
                            ->orderBy('created_at', 'desc');
    }

    public function readNotifications()
    {
        return $this->notifications()
                            ->whereNotNull('read_at');
    }

    public function unreadNotifications()
    {
        return $this->notifications()
                            ->whereNull('read_at');
    }
}

由上可见,HasDatabaseNotifications 通过 关联DatabaseNotification类读取通知,在DatabaseNotification类中定义了$table = 'notifications' 。
此外 获取未读通知 unreadNotifications 方法 是根据 read_at 字段作为判断条件。
还有 DatabaseNotification 模型类中 定义了 标记消息已读的方法 markAsRead 和 标记消息未读的方法markAsUnread 。

2.触发通知说明

Notifiable中引用了RoutesNotifications trait ,而RoutesNotifications定义了 notify($instance) 方法用来发送通知

3.相关代码

app/Observers/ReplyObserver.php:

use App\Notifications\TopicReplied;
class ReplyObserver
{
    public function created(Reply $reply)
    {
        $topic = $reply->topic;
        $topic->increment('reply_count', 1);

        // 通知作者话题被回复了
        $topic->user->notify(new TopicReplied($reply));
    }
}

app/Models/User.php

use Auth;

class User extends Authenticatable
{
    use Notifiable {
        notify as protected laravelNotify; // 把系统的notify方法重命名为laravelNotify
    }
    // 对notify()方法的重写
    public function notify($instance)
    {
        // 如果要通知的人是当前用户,就不必通知了!
        if ($this->id == Auth::id()) {
            return;
        }
        $this->increment('notification_count');
        $this->laravelNotify($instance);
    }
}

相关视图

生成控制器

php artisan make:controller NotificationsController

修改路由

Route::resource('notifications', 'NotificationsController', ['only' => ['index']]);

通知视图

class NotificationsController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
    }

    public function index()
    {
        // 获取登录用户的所有通知
        $notifications = Auth::user()->notifications()->paginate(20);
        return view('notifications.index', compact('notifications'));
    }
}

标记通知为已读

在 app/Models/User.php 中添加

public function markAsRead()
{
    $this->notification_count = 0;
    $this->save();
    $this->unreadNotifications->markAsRead();
}

修改NotificationsController中index()添加

// 标记为已读,未读数量清零
Auth::user()->markAsRead();
本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由系统于 4年前 自动加精
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 2

如果消息通知 有分类,应该如何进行操作,
1.评论 和点赞你的 话题 消息通知
2.订单的状态消息通知
3.系统官方推送的消息通知

file

4年前 评论

@gyp719 同问,这问题你有解决么

4年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!