Laravel 消息通知

Laravel 还支持通过多种频道发送通知,包括邮件、短信 (通过 Vonage,原来叫 Nexmo),以及 Slack。通知还能存储到数据库以便后续在 Web 页面中显示。

  • 邮箱发送通知
  • 数据库通知
  • 广播通知
  • 短信通知

准备流程

  • 需要执行发送通知的类继承下Trait
<?php

namespace App\Models;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
    use Notifiable;
}

这个可以用到任意类,你可以写在别的地方

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Notifications\Notifiable;

class Admin extends Model
{
    //
    use Notifiable;
}
  • 创建消息通知处理类
php artisan make:notification MailNotification
  • 发送消息
use App\Notifications\InvoicePaid;

$user->notify(new InvoicePaid($invoice));

或是

Notification::send($users, new InvoicePaid($invoice));

总结:模型继承下类,创建处理消息类,执行发送,默认是发送邮箱通知

例子

web.php

Route::get('to/{id}','HomeController@to');
Route::get('show/{id}','HomeController@show');

HomeController

<?php

namespace App\Http\Controllers;

use App\Models\Admin;
use App\Notifications\MailNotification;
use Illuminate\Support\Facades\Notification;

class HomeController extends  Controller
{

    //推送给谁
    public function to($id=1){
        $user =Admin::find($id);
        $user->notify(new MailNotification());

    }
    //显示通知
    public function show($id=1){
        $user =Admin::find($id);
        foreach ($user->notifications as $notification) {
            echo $notification->type;
        }

    }
}
<?php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;

class MailNotification extends Notification
{
    use Queueable;

    /**
     * Create a new notification instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Get the notification's delivery channels.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return ['mail'];
    }

    /**
     * Get the mail representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return \Illuminate\Notifications\Messages\MailMessage
     */
    public function toMail($notifiable)
    {
        return (new MailMessage)
                    ->line('你好我是测试消息通知')
                    ->action('查看', url('/'))
                    ->line('感谢您的支持');
    }

    /**
     * Get the array representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function toArray($notifiable)
    {
        return [
            //
        ];
    }
}

黑白课堂
这里我把邮箱驱动设置了log
.env

MAIL_MAILER=log

数据库发送准备工作

php artisan notifications:table

php artisan migrate

发送指定频道

    public function via($notifiable)
    {
        return ['mail'];
    }

传递传送指定

   public function via($notifiable)
    {
    //notifiable就是模型的注入类数据
        return $notifiable->isDb?['database']:['mail'];
    }
 public function to($id=1){
        $user =Admin::find($id);
        $user->isDb=1;//数据库发送
        $user->notify(new MailNotification());
        //dd($r);

    }

黑白课堂

这里使用 laravel 一对多态的数据库设计

notifiable_type
notifiable_id

data 字段类存储我们的数据,如果你想要存储数据需要设置下我们存储数据库的字段信息

  public function toArray($notifiable)
    {
        return $this->msg;
    }

黑白课堂
如果要将通知存储到数据库中,您应该在通知类中定义 toDatabase 或 toArray 方法。该方法应该接受一个 $notifiable 实体并返回一个原生的 PHP 数组。返回的数组将会被编码成为 JSON 并存储到您的 notifications 表的 data 字段中

注意

toArray 还用于 broadcast 频道来确定要向 JavaScript 客户端广播哪些数据。如果希望为 database 和 broadcast 频道使用两种不同的数组表示形式,则应 定义 toDatabase方法而不是 toArray 方法

其他几个通知不做介绍

本地化通知

Laravel 允许您以当前语言环境之外的其他语言发送通知,并且会在通知队列时记住该语言环境。

$user->notify((new InvoicePaid($invoice))->locale('es'));

Notification::locale('es')->send($users, new InvoicePaid($invoice));

通知事件

当通知被发送后,通知系统会触发Illuminate\Notifications\Events\NotificationSent 事件,该事件实例包含被通知的实体(如用户)和通知实例本身。你可以在EventServiceProvider 中为该事件注册监听器:

protected $listen = [
    'Illuminate\Notifications\Events\NotificationSent' => [
        'App\Listeners\LogNotification',
    ],
];

可以访问事件的 notifiable、 notification 和 channel 属性以了解通知接收者和通知本身.

自定义通知

创建驱动

比如我们要把消息压入到redis,首先定义一个驱动通道

<?php
namespace App\Channels;
use Illuminate\Notifications\Notification;

class RedisChannel
{
    /**
     * 发送指定的通知。
     *
     * @param  mixed  $notifiable
     * @param  \Illuminate\Notifications\Notification  $notification
     * @return void
     */
    public function send($notifiable, Notification $notification)
    {
         $notification->toRedis($notifiable);

    }
}
  • send 方法必须的

创建消息处理类

php artisan make:notification RedisNotification
<?php

namespace App\Notifications;

use App\Channels\RedisChannel;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Facades\Redis;

class RedisNotification extends Notification
{
    use Queueable;
    public $redisName;
    /**
     * Create a new notification instance.
     *
     * @return void
     */
    public function __construct($redisName)
    {
        //
        $this->redisName=$redisName;
    }

    /**
     * Get the notification's delivery channels.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return [RedisChannel::class];
    }

    public function toRedis($notifiable){
        //因为驱动调用了这个方法,所以需要执行这个方法,总之在这里编写我们要操作的执行业务代码。
        $name=$this->redisName;
        Redis::rPush($name,$notifiable->id);//压入队列
    }

}

消息通知使用场景

  • 短信发送
  • 消息提醒
  • 聊天通知
  • 消息推送

消息推送队列

有时候我们在处理业务的时候,会碰到一些耗时的写入,比如图片发送等推送,可能需要有1点时间上传,那么我们这个时候,如果让用户一直等,那体验很查,那我们这个时候可以队列一下,让队列帮我们去处理。 implements ShouldQueue 一下即可

<?php

namespace App\Notifications;

use App\Channels\RedisChannel;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Facades\Redis;

class RedisNotification extends Notification implements ShouldQueue
{
    use Queueable;
    public $redisName;
    /**
     * Create a new notification instance.
     *
     * @return void
     */
    public function __construct($redisName)
    {
        //
        $this->redisName=$redisName;
    }

    /**
     * Get the notification's delivery channels.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return [RedisChannel::class];
    }

    public function toRedis($notifiable){
        $name=$this->redisName;

        sleep(20);//20秒压入等待测试
        Redis::rPush($name,$notifiable->id);//压入队列
    }

}

我们上面写了20秒才完成,那么我们来测试下,如果不加队列需要等待20秒,加入之后测试下看看
黑白课堂 ![黑白课堂]

这个必须把 .env 下的队列改成 redis,不然你默认的是同步操作

QUEUE_CONNECTION=redis

好了,我们现在把上面implements ShouldQueue 移除,看看效果,
是不是要等待20秒
黑白课堂

那么我们有时候需要分开队列的名称,默认都是

"laravel_database_queues:default"
"laravel_database_queues:default:notify"

我们想改下呢,

<?php

namespace App\Notifications;

use App\Channels\RedisChannel;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Facades\Redis;

class RedisNotification extends Notification implements ShouldQueue
{
    use Queueable;
    public $redisName;
    /**
     * Create a new notification instance.
     *
     * @return void
     */
    public function __construct($redisName)
    {
        //
        $this->redisName=$redisName;
    }

    /**
     * Get the notification's delivery channels.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return [RedisChannel::class];
    }

    public function toRedis($notifiable){
        $name=$this->redisName;
        sleep(20);//20秒压入等待测试
        Redis::rPush($name,$notifiable->id);//压入队列
    }
    //这里定义我们的名字
    public function viaQueues()
    {
        return [
            RedisChannel::class => 'redis-queue',

        ];
    }

}

我们再来推送一下

"laravel_database_queues:redis-queue:notify"
"laravel_database_queues:redis-queue"

完成我们的自定义,那么我们要执行这个操作,怎么操作呢,

php artisan queue:work redis --queue=redis-queue

相关知识可查阅这个 点击查看队列

评论区 (0)

没有记录
支持 markdown,图片截图粘贴拖拽都可以自动上传。
黑白课堂

黑白课堂 · 技术专家

专业PHP开发

年度VIP 站长创业者玉树凌风每天醒来0收入
查看更多

最新视频课程