简介
Laravel 自带了一套消息通知系统,还支持多种通知频道,包括数据库、邮件、短信等。
此处我们详细说明数据库通知频道
创建通知类
Laravel 中一条通知就是一个类,(通常在 app/Notifications 文件里),命令如下:1
php artisan make:notification TopicReplied
每个通知类都包含一个 via 方法 以及多个消息构造方法( 如toMail或toDatabase )
via() 决定了通知在哪个频道上发送,如在数据库作为通知:1
2
3
4
5public function via($notifiable)
{
// 开启通知的频道
return ['database'];
}
而toDatabase($notifiable)方法会返回一个数组将被转化为json格式并存储到 notifications 数据表中的data字段中。
数据库通知
数据库通知频道会在一张数据表里存储所有信息,包含了比如通知类型、JSON 格式数据等描述通知的信息。
可以查询此表的内容在应用界面上展示通知。
1.首先创建生成迁移表
1 | php artisan notifications:table |
会生成 database/migrations/{$timestamp}_create_notifications_table.php 迁移文件
2.生成数据表
1 | php artisan migrate |
3.记录未读通知
在users表中新增 notification_count 字段,用来跟踪用户有多少通知1
php artisan make:migration add_notification_count_to_users_table --table=users
打开生成的文件,修改如下:1
2
3
4
5
6
7
8
9
10
11
12
13public 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');
});
}
应用数据库修改1
php artisan migrate
发送通知
1.读取通知说明
在User模型类使用了Notifiable trait,而Notifiable中又引入了 HasDatabaseNotifications trait。
HasDatabaseNotifications中有3个函数,分别是 获取所有通知、获取未读通知 和 已读通知。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20trait 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:1
2
3
4
5
6
7
8
9
10
11
12use 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.php1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18use 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);
}
}
相关视图
生成控制器1
php artisan make:controller NotificationsController
修改路由1
Route::resource('notifications', 'NotificationsController', ['only' => ['index']]);
通知视图1
2
3
4
5
6
7
8
9
10
11
12
13
14class 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 中添加1
2
3
4
5
6public function markAsRead()
{
$this->notification_count = 0;
$this->save();
$this->unreadNotifications->markAsRead();
}
修改NotificationsController中index()添加1
2// 标记为已读,未读数量清零
Auth::user()->markAsRead();