PS:本次主要记录一下laravel 自带的消息通知Notification的实现
php artisan notifications:table
php artisan migrate
这里模拟点赞通知
php artisan make:notification UserSupport
如果implements ShouldQueue这个接口的话就会异步队列执行,如果去掉的话就是同步执行。
<?php
/**
* 模拟用户点赞通知
* laravel 通知表 notifications
* 点赞表 user_support
* 作者表 users
* 用户表 user_info
*/
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
use App\Models\UserSupport as UserSupportModel;
class UserSupport extends Notification implements ShouldQueue
{
use Queueable;
public $support;
public function __construct(UserSupportModel $support)
{
// 注入回复实体,方便 toDatabase 方法中的使用
$this->support = $support;
}
public function via($notifiable)
{
// 开启通知的频道
return ['mail','database'];
}
public function toMail($notifiable)
{
return (new MailMessage)
->line('The introduction to the notification.')
->action('Notification Action', 'www.baidu.com')
->line('Thank you for using our application!');
}
public function toDatabase($notifiable)
{
$user = $this->support->user;
$pic = rand(1,10);
// 存入数据库里的数据
return [
'support_id' => $this->support->id,
'doname' => $this->support->UserInfo->name,
'toname' => $user->name,
'pic' => $pic.'.png',
'cont' => '内容内容'
];
}
每个通知类都有个 via() 方法,它决定了通知在哪个频道上发送。我们加上 database 数据库来作为通知频道。
因为使用数据库通知频道,我们需要定义 toDatabase()。这个方法接收 $notifiable 实例参数并返回一个普通的 PHP 数组。这个返回的数组将被转成 JSON 格式并存储到通知数据表的 data 字段中。
<?php
namespace App\Observers;
use App\Models\UserSupport;
use App\Notifications\UserSupport as UserSupportNotify;//引入通知类
class SupportObserver
{
public function created(UserSupport $userSupport)
{
// 通知作者被点赞了
//notify 方法稍后再user模型中定义
$userSupport->user->notify(new UserSupportNotify($userSupport));
}
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Auth;
class User extends Authenticatable
{
use Notifiable {
notify as protected laravelNotify;
// Notifiable 的trait里面有notify方法,此处我们给它个别名
}
public function notify($instance)
{
// 如果要通知的人是当前用户,就不必通知了!
if ($this->id == Auth::id()) {
return;
}
// 只有数据库类型通知才需提醒,Email直接发送 或者其他的都 Pass
if (method_exists($instance, 'toDatabase')) {
$this->increment('notification_count');//字段加一
}
$this->laravelNotify($instance);//发送通知
}
请注意顶部 Auth 的引入。
我们对 notify() 方法做了一个巧妙的重写,现在每当你调用 $user->notify() 时, users 表里的 notification_count 将自动 +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');
}
}
控制器获取数据
$uid = Auth::id();
$user = User::find($uid);
// 已读未读是有一个 read_at 字段
// dd($user->unreadNotifications); // 获取所有未读通知
// dd($user->readNotifications); // 获取所有已读通知
// dd($user->notifications); // 获取所有通知
$unreadNotifications = $user->unreadNotifications;//用来消息通知
$userlist = User::select('id','name')->get();//用来点赞
return view('admin.index',compact('unreadNotifications','userlist'));
模板中判断是否有通知
{{ Auth::user()->notification_count > 0 ? ‘block’ : ‘none’ }}
{{ Auth::user()->notification_count }}
遍历展示通知数据
@foreach($unreadNotifications as $v)
<a href="#" class="dropdown-item notify-item">
<div class="notify-icon bg-faded">
<img src="assets/images/avatars/avatar{{$v['data']['pic']}}" >
</div>
<p class="notify-details">
<b>{{$v['data']['doname']}}</b>
<span>{{$v['data']['cont']}}</span>
<small class="text-muted">{{$v['created_at']}}</small>
</p>
</a>
@endforeach
其中data数据就是通知类里toDatabase方法里存入数据量里的数据,如下图
再User模型里 app/Models/user.php 添加方法
public function markAsRead()
{
// 标记为已读,未读数量清零
$this->notification_count = 0;
$this->save();
//更改notifications表read_at值
$this->unreadNotifications->markAsRead();
}
再控制器里调用这个方法就行
markAsRead其实就是在Illuminate\Notifications----》DatabaseNotification.php里将read_at修改了
public function support(Request $request){
if($request->ajax()){
$uid = $request->post('uid','1');
$usersup = UserSupport::Create(['uid'=>$uid,'user_id'=>'33']);
return true;
}
$IP = $request->getClientIp();
return '非法请求,IP:'.$IP;
}
点赞触发create时,观察者则监听到,下发通知