消息通知

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

    通常,通知都是简短、有信息量的消息,用于通知用户应用中发生了什么。举例来说,如果你是在编写一个在线交易的应用,你应该会通过邮件和短信频道类给用户发送一条 「账单支付」 的通知。

    创建通知

    Laravel 中一条通知就是一个类 (通常存放在 文件夹下)。看不到的话不要担心,运行下 make:notification 命令就能创建了:

    这条命令会在 app/Notifications 目录下生成一个新的通知类。这个类包含 via 方法以及一个或多个消息构建的方法 (比如 toMail 或者 toDatabase) ,它们会针对指定的渠道把通知转换为对应的消息。

    发送通知

    通知可以通过两种方法发送:Notifiable trait 的 notify 方法或 Notification facade。首先让我们来探讨下使用 trait:

    1. <?php
    2. namespace App;
    3. use Illuminate\Notifications\Notifiable;
    4. use Illuminate\Foundation\Auth\User as Authenticatable;
    5. class User extends Authenticatable
    6. {
    7. use Notifiable;
    8. }

    默认的 App\User 模型中使用了这个 trait,它包含着一个可以用来发送通知的方法: notifynotify 方法需要一个通知实例做参数:

    1. use App\Notifications\InvoicePaid;
    2. $user->notify(new InvoicePaid($invoice));

    使用 Notification Facade

    另外,你可以通过 Notification 来发送通知。它主要用在当你给多个可接收通知的实体发送的时候,比如给用户集合发送通知。使用 Facade 发送通知的话,要把可以接收通知和通知的实例传递给 send 方法:

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

    发送指定频道

    每个通知类都会有个 via 方法,它决定了通知会在哪个频道上发送。开箱即用的频道有 maildatabasebroadcastnexmoslack

    Tip:如果你想使用其他的频道,比如 Telegram 或者 Pusher,你可以去看下社区驱动的 Laravel 通知频道网站

    via 方法接收一个 $notifiable 实例。这个实例将是通知实际发送到的类的实例。你可以用 $notifiable 来决定通知用哪些频道来发送:

    1. /**
    2. * 获取通知发送频道。
    3. *
    4. * @param mixed $notifiable
    5. * @return array
    6. */
    7. public function via($notifiable)
    8. {
    9. return $notifiable->prefers_sms ? ['nexmo'] : ['mail', 'database'];
    10. }

    通知队列

    {注:} 使用通知队列前需要配置队列并 。

    发送通知可能是耗时的,尤其是通道需要调用额外的 API 来传输通知。为了加速应用的响应时间,可以将通知推送到队列中异步发送,而要实现推送通知到队列,可以让对应通知类实现 ShouldQueue 接口并使用 Queueable trait 。 如果通知类是通过 make:notification 命令生成的,那么该接口和 trait 已经默认导入,你可以快速将它们添加到通知类:

    1. <?php
    2. namespace App\Notifications;
    3. use Illuminate\Bus\Queueable;
    4. use Illuminate\Notifications\Notification;
    5. use Illuminate\Contracts\Queue\ShouldQueue;
    6. class InvoicePaid extends Notification implements ShouldQueue
    7. {
    8. use Queueable;
    9. // ...
    10. }

    ShouldQueue 接口被添加到通知类以后,你可以像之前一样正常发送通知,Laravel 会自动检测到 ShouldQueue 接口然后将通知推送到队列:

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

    如果你想要延迟通知的发送,可以在通知实例后加上 delay 方法:

    1. $when = now()->addMinutes(10);
    2. $user->notify((new InvoicePaid($invoice))->delay($when);

    按需通知

    有时候你可能需要发送通知给某个用户,但是该用户不存在于应用的用户系统中,要实现这一目的,我们使用 Notification::route 方法在发送通知之前指定特别的通知路由:

    1. Notification::route('mail', 'taylor@example.com')
    2. ->route('nexmo', '5555555555')
    3. ->notify(new InvoicePaid($invoice));

    邮件通知

    格式化邮件消息

    如果通知支持以邮件方式发送,你需要在通知类上定义一个 toMail 方法。该方法会接收一个 $notifiable 实体并返回 Illuminate\Notifications\Messages\MailMessage 实例。邮件消息可以包含多行文本以及对动作的调用,让我们来看一个 toMail 方法的示例:

    1. /**
    2. * 获取通知对应的邮件。
    3. *
    4. * @param mixed $notifiable
    5. */
    6. public function toMail($notifiable)
    7. {
    8. $url = url('/invoice/'.$this->invoice->id);
    9. return (new MailMessage)
    10. ->greeting('Hello!')
    11. ->line('One of your invoices has been paid!')
    12. ->action('View Invoice', $url)
    13. ->line('Thank you for using our application!');
    14. }

    在这个例子中,我们注册了一条问候、一行文本、对动作的调用以及另一行文本。 MailMessage 对象提供的这些方法让格式化短小的事务邮件变得简单快捷。mail 通道会将消息组件转化为美观的、响应式的、带有纯文本副本的 HTML 邮件模板。下面是一个通过 mail 通道生成的邮件示例:

    {注:} 发送邮件通知时,确保在配置文件 config/app.php 中设置了 name 的值,该值将会用在邮件通知消息的头部和尾部。

    其他通知格式化选项

    除了在通知类中定义多行文本之外,你还可以使用 view 方法来指定一个自定义的、用于渲染通知邮件的模板:

    1. /**
    2. *
    3. * @param mixed $notifiable
    4. * @return \Illuminate\Notifications\Messages\MailMessage
    5. */
    6. public function toMail($notifiable)
    7. {
    8. return (new MailMessage)->view(
    9. 'emails.name', ['invoice' => $this->invoice]
    10. );
    11. }

    此外,你可以从 toMail 方法中返回一个 :

    1. use App\Mail\InvoicePaid as Mailable;
    2. /**
    3. * Get the mail representation of the notification.
    4. *
    5. * @param mixed $notifiable
    6. * @return Mailable
    7. */
    8. public function toMail($notifiable)
    9. {
    10. return (new Mailable($this->invoice))->to($this->user->email);
    11. }

    错误消息

    一些通知会告知用户错误信息,例如失败的订单支付。你可以在构建消息的时候调用 error 方法来指示该邮件消息表示错误信息。在邮件消息中使用 error 方法时,动作按钮将会变成红色:

    1. /**
    2. * 获取通知邮件。
    3. *
    4. * @param mixed $notifiable
    5. * @return \Illuminate\Notifications\Message
    6. */
    7. public function toMail($notifiable)
    8. {
    9. return (new MailMessage)
    10. ->error()
    11. ->subject('Notification Subject')
    12. ->line('...');
    13. }

    自定义接收人

    通过 mail 通道发送通知时,通知系统会自动在被通知实体上查找 email 属性,你可以通过在该实体上定义一个 routeNotificationForMail 来自定义使用哪个邮箱地址发送通知:

    1. <?php
    2. namespace App;
    3. use Illuminate\Notifications\Notifiable;
    4. use Illuminate\Foundation\Auth\User as Authenticatable;
    5. class User extends Authenticatable
    6. {
    7. use Notifiable;
    8. /**
    9. * 邮件通道通知的路由。
    10. *
    11. * @param \Illuminate\Notifications\Notification $notification
    12. * @return string
    13. */
    14. public function routeNotificationForMail($notification)
    15. {
    16. return $this->email_address;
    17. }
    18. }

    自定义主题

    默认情况下,邮件的主题就是格式为 「标题风格」 的通知类名,因此,如果通知类被命名为 InvoicePaid,邮件的主题就是 Invoice Paid,如果你想要为消息指定明确的主题,可以在构建消息的时候调用 subject 方法:

    /**
     * 获取通知的邮件表示。
     *
     * @param  mixed  $notifiable
     * @return \Illuminate\Notifications\Messages\MailMessage
     */
    public function toMail($notifiable)
    {
        return (new MailMessage)
                    ->subject('Notification Subject')
                    ->line('...');
    }

    自定义模板

    你可以通过发布通知扩展包的资源来修改邮件通知所使用的 HTML 和纯文本模板。运行完下面这个命令之后,邮件通知模板将会存放到 resources/views/vendor/notifications 目录:

    php artisan vendor:publish --tag=laravel-notifications

    要生成带有相应 Markdown 模板的通知,可以在使用 Artisan 命令 make:notification 时带上 —markdown 选项:

    php artisan make:notification InvoicePaid --markdown=mail.invoice.paid

    和其他邮件通知一样,使用 Markdown 模板的通知类也要定义一个 toMail 方法。不过,你可以使用 markdown 方法取代构造通知的 lineaction 方法来指定要使用的 Markdown 模板名称:

    /**
     * 获取通知的邮件表示。
     *
     * @param  mixed  $notifiable
     * @return \Illuminate\Notifications\Messages\MailMessage
     */
    public function toMail($notifiable)
    {
        $url = url('/invoice/'.$this->invoice->id);
    
        return (new MailMessage)
                    ->subject('Invoice Paid')
                    ->markdown('mail.invoice.paid', ['url' => $url]);
    }

    编写消息

    Markdown 邮件通知联合使用了 Blade 组件和 Markdown 语法,从而让你在不脱离 Laravel 预置组件的情况下轻松构建通知:

    @component('mail::message')
    # Invoice Paid
    
    Your invoice has been paid!
    
    @component('mail::button', ['url' => $url])
    View Invoice
    @endcomponent
    
    Thanks,<br>
    {{ config('app.name') }}
    @endcomponent

    按钮组件

    按钮组件渲染一个居中的按钮链接。该组件接收两个参数, url 和可选的 color,支持的颜色有 bluegreenred。你可以添加任意数量的按钮组件到消息中:

    面板组件

    面板组件将给定的文字区块渲染到一个面板中,并且有一个淡淡的背景色与周围的消息区分开。适用于需要引起注意的文字区块:

    @component('mail::panel')
    This is the panel content.
    @endcomponent

    表格组件

    表格组件允许你将一个 Markdown 表格转化为 HTML 表格。该组件接收 Markdown 表格作为其内容。表格列对齐支持使用默认的 Markdown 表格列对齐语法:

    @component('mail::table')
    | Laravel       | Table         | Example  |
    | ------------- |:-------------:| --------:|
    | Col 2 is      | Centered      | $10      |
    | Col 3 is      | Right-Aligned | $20      |
    @endcomponent

    自定义组件

    你可以导出所有 Markdown 通知组件到应用中进行自定义,要导出组件,使用 Artisan 命令 vendor:publish 来发布 laravel-mail 资源标签:

    php artisan vendor:publish --tag=laravel-mail

    该命令会发布 Markdown 邮件通知组件到 resources/views/vendor/mail 目录。 mail 目录包含 htmlmarkdown 目录,每个子目录中又包含各自的所有有效组件。你可以按照自己的喜好自由编辑这些组件。

    自定义CSS

    导出组件之后, resources/views/vendor/mail/html/themes 目录将会包含一个默认的 default.css 文件,你可以在这个文件中自定义 CSS,这样 Markdown 通知的 HTML 样式就会自动调整。

    {注:} 如果你想要为 Markdown 组件构建全新的主题,只需在 html/themes 目录中编写一个新的 CSS 文件并修改 mail 配置文件的 theme 选项即可。

    数据库通知

    预备知识

    database 通知通道会在数据表中存储通知信息,该表包含诸如通知类型以及用于描述通知的自定义 JSON 数据之类的信息。

    你可以在用户界面中查询这个数据表来展示通知,不过,在此之前,需要创建数据表来保存信息,你可以使用 notifications:table 命令来生成迁移文件然后以此生成相应数据表:

    php artisan notifications:table
    
    php artisan migrate

    格式化数据库通知

    如果通知支持存入数据库表,就为通知类需要定义 toDatabasetoArray 方法。此方法接受 $notifiable 实体作参数并返回原生 PHP 数组。返回的数据将被编码为 JSON 并存储到 notifications 表的 data 列。来看一个 toArray 方法示例:

    
    

    toDatabase Vs. toArray

    toArray 方法还可以使用 broadcast 通道来判断哪些数据被广播到 JavaScript 客户端。如果针对 databasebroadcast 通道分别有两个不同的数组表示,你需要定义 toDatabase 方法代替 toArray 方法。

    访问通知

    一旦通知存入数据库,就需要适当的方法自通知实体访问它们。 包含在 Lareval 的默认 App\User 模型带有 Illuminate\Notifications\Notifiable trait,它的notifications Eloquent 关联方法能返回实体通知。要获取通知,可以像其它 Eloquent 关联方法一样访问此方法。默认情况下,通知按照 created_at 时间戳排序:

    $user = App\User::find(1);
    
    foreach ($user->notifications as $notification) {
        echo $notification->type;
    }

    若要只获取 「未读」通知,可以使用 unreadNotifications 关联方法。同样这些通知按照 created_at 时间戳排序:

    $user = App\User::find(1);
    
    foreach ($user->unreadNotifications as $notification) {
        echo $notification->type;
    }

    标记通知已读

    通常,在用户阅览一条通知之后,你会想将其标识为「已读」。 Illuminate\Notifications\Notifiable trait 提供了 markAsRead 方法,它更新数据库中通知记录的 read_at 列:

    $user = App\User::find(1);
    
    foreach ($user->unreadNotifications as $notification) {
        $notification->markAsRead();
    }

    可以在通知控制集合上直接使用 markAsRead 方法代替循环调用通知:

    $user->unreadNotifications->markAsRead();

    还可以使用指更新将所有的通知标为已读,而不从数据库中读取它们:

    $user = App\User::find(1);
    
    $user->unreadNotifications()->update(['read_at' => now()]);

    可以使用 delete 方法从表中整个删除通知:

    $user->notifications()->delete();

    广播通知

    预备知识

    广播通知前,你需要配置和熟悉 Laravel 的 服务。事件广播提供了在 JavaScript 客户端响应服务端触发 Laravel 事件的方法。

    格式化广播通知

    broadcast 通道使用 Laravel 的 event broadcasting 服务广播通知,它允许 JavaScript客户端实时捕获通知。如果通知支持广播,你就需要在通知类上定义 toBroadcast 方法。此方法接受 $notifiable 实体作为参数,并返回 BroadcastMessage 实例。返回的数据将被编码为 JSON 并广播给 JavaScript 客户端。我们来看一个 toBroadcast 方法示例

    use Illuminate\Notifications\Messages\BroadcastMessage;
    
    /**
     * 获取通知的可广播表示。
     *
     * @param  mixed  $notifiable
     * @return BroadcastMessage
     */
    public function toBroadcast($notifiable)
    {
        return new BroadcastMessage([
            'invoice_id' => $this->invoice->id,
            'amount' => $this->invoice->amount,
        ]);
    }

    广播队列配置

    所有的广播通知都被放入广播队列。想要配置用于广播操作的队列连接或者队列名称,需要使用 BroadcastMessageonConnectiononQueue 方法:

    return (new BroadcastMessage($data))
                    ->onConnection('sqs')
                    ->onQueue('broadcasts');

    Tip:除了指定的数据,广播通知还包含 type 域,它包括通知类的类名。

    通知将会以格式化为 {notifiable}.{id} 的形式在私有频道上广播,因此,如果你要发送通知到 ID 为 1App\User 实例,那么该通知将会在私有频道 App.User.1 上进行广播,如果使用了 ,可以使用辅助函数 notification 轻松在某个频道上监听通知:

    Echo.private('App.User.' + userId)
        .notification((notification) => {
            console.log(notification.type);
        });

    自定义通知通道

    如果你想要自定义被通知实体在某个通道上接收广播通知,可以在被通知实体上定义一个 receivesBroadcastNotificationsOn 方法:

    <?php
    
    namespace App;
    
    use Illuminate\Notifications\Notifiable;
    use Illuminate\Broadcasting\PrivateChannel;
    use Illuminate\Foundation\Auth\User as Authenticatable;
    
    class User extends Authenticatable
    {
        use Notifiable;
    
        /**
         * 用户接收广播通知的通道。
         *
         * @return string
         */
        public function receivesBroadcastNotificationsOn()
        {
            return 'users.'.$this->id;
        }
    }

    短信(SMS)通知

    预备知识

    composer require laravel/nexmo-notification-channel

    下一步,你需要在配置文件 config/services.php 中进行相应配置。你可以参考以下示例配置:

    'nexmo' => [
        'key' => env('NEXMO_KEY'),
        'secret' => env('NEXMO_SECRET'),
        'sms_from' => '15556666666',
    ],

    sms_from 配置项就是你用于发送短信消息的手机号码,你需要在 Nexmo 控制面板中为应用生成一个手机号码。

    格式化短信通知

    如果通知支持以短信方式发送,那么你需要在通知类上定义一个 toNexmo 方法。该方法接收一个 $notifiable 实体并返回 Illuminate\Notifications\Messages\NexmoMessage 实例:

    /**
     * Get the Nexmo / SMS representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return NexmoMessage
     */
    public function toNexmo($notifiable)
    {
        return (new NexmoMessage)
                    ->content('Your SMS message content');
    }

    Unicode 内容

    如果你的短信消息包含 Unicode 字符,需要在构造 NexmoMessage 实例时调用 unicode 方法:

    自定义 "发送" 号码

    如果你要通过与配置文件 config/services.php 中指定的手机号不同的其他号码发送通知,可以使用 NexmoMessage 实例上的 from 方法:

    /**
     * Get the Nexmo / SMS representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return NexmoMessage
     */
    public function toNexmo($notifiable)
    {
        return (new NexmoMessage)
                    ->content('Your SMS message content')
                    ->from('15554443333');
    }

    短信通知路由

    使用 nexmo 通道发送通知的时候,通知系统会自动在被通知实体上查找 phone_number 属性。如果你想要自定义通知被发送到的手机号码,可以在该实体上定义一个 routeNotificationForNexmo 方法:

    <?php
    
    namespace App;
    
    use Illuminate\Notifications\Notifiable;
    use Illuminate\Foundation\Auth\User as Authenticatable;
    
    class User extends Authenticatable
    {
        use Notifiable;
    
        /**
         * Route notifications for the Nexmo channel.
         *
         * @param  \Illuminate\Notifications\Notification  $notification
         * @return string
         */
        public function routeNotificationForNexmo($notification)
        {
            return $this->phone;
        }
    }

    预备知识

    在通过 Slack 发送通知前,必须通过 Composer 安装 Slack 通知通道:

    composer require laravel/slack-notification-channel

    此外,你还要为 Slack 组配置一个 集成。该集成会在你进行 Slack 通知路由 的时候提供一个URL。

    格式化 Slack 通知

    如果通知支持通过 Slack 消息发送,则需要在通知类上定义一个 toSlack 方法,该方法接收一个 $notifiable 实体并返回 Illuminate\Notifications\Messages\SlackMessage 实例,该实例包含文本内容以及格式化额外文本或数组字段的“附件”。让我们来看一个基本的 toSlack 使用示例:

    /**
     * Get the Slack representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return SlackMessage
     */
    public function toSlack($notifiable)
    {
        return (new SlackMessage)
                    ->content('One of your invoices has been paid!');
    }

    在这个例子中,我们只发送一行简单的文本到 Slack,最终创建的消息如下:

    basic-slack-notification.png

    Customizing The Sender & Recipient

    你可以使用 fromto 方法自定义发送者和接收者, from 方法接收一个用户名和 emoji 标识,而 to 方法接收通道或用户名:

    /**
     * Get the Slack representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return SlackMessage
     */
    public function toSlack($notifiable)
    {
        return (new SlackMessage)
                    ->from('Ghost', ':ghost:')
                    ->to('#other')
                    ->content('This will be sent to #other');
    }

    还可以使用图片作为 logo 用以取代 emoji:

    /**
     * Get the Slack representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return SlackMessage
     */
    public function toSlack($notifiable)
    {
        return (new SlackMessage)
                    ->from('Laravel')
                    ->image('https://laravel.com/favicon.png')
                    ->content('This will display the Laravel logo next to the message');
    }

    Slack 附件

    你还可以添加“附件”到 Slack 消息。相对简单文本消息,附件可以提供更加丰富的格式选择。在这个例子中,我们会发送一个在应用程序中出现的异常错误通知,包含查看更多异常细节的链接:

    /**
     * Get the Slack representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return SlackMessage
     */
    public function toSlack($notifiable)
    {
        $url = url('/exceptions/'.$this->exception->id);
    
        return (new SlackMessage)
                    ->error()
                    ->content('Whoops! Something went wrong.')
                    ->attachment(function ($attachment) use ($url) {
                        $attachment->title('Exception: File Not Found', $url)
                                   ->content('File [background.jpg] was not found.');
                    });
    }

    上述代码会生成如下 Slack 消息:

    附件还允许你指定要呈献给用户的数组数据。为了提高可读性,给定的数组会以表格形式展示:

    /**
     * Get the Slack representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return SlackMessage
     */
    public function toSlack($notifiable)
    {
        $url = url('/invoices/'.$this->invoice->id);
    
        return (new SlackMessage)
                    ->success()
                    ->content('One of your invoices has been paid!')
                    ->attachment(function ($attachment) use ($url) {
                        $attachment->title('Invoice 1322', $url)
                                   ->fields([
                                        'Title' => 'Server Expenses',
                                        'Amount' => '$1,234',
                                        'Via' => 'American Express',
                                        'Was Overdue' => ':-1:',
                                    ]);
                    });
    }

    上述代码会生成如下 Slack 消息:

    slack-fields-attachment.png

    Markdown 附件内容

    如果一些附件字段包含 Markdown,可以使用 markdown 方法来构建 Slack 用以解析并显示以 Markdown 格式编写的附件字段,该方法支持的值包括 pretexttextfields。想要了解更多关于 Slack 格式化的信息,查看 :

    /**
     * Get the Slack representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return SlackMessage
     */
    public function toSlack($notifiable)
    {
        $url = url('/exceptions/'.$this->exception->id);
    
        return (new SlackMessage)
                    ->error()
                    ->content('Whoops! Something went wrong.')
                    ->attachment(function ($attachment) use ($url) {
                        $attachment->title('Exception: File Not Found', $url)
                                   ->content('File [background.jpg] was *not found*.')
                                   ->markdown(['text']);
                    });
    }

    Slack 通知路由

    要路由 Slack 通知到适当的位置,需要在被通知的实体上定义一个 routeNotificationForSlack 方法,这将会返回通知被发送到的 Webhook URL。Webhook URL 可通过在 Slack 组上添加一个 "Incoming Webhook" 服务来生成:

    <?php
    
    namespace App;
    
    use Illuminate\Notifications\Notifiable;
    use Illuminate\Foundation\Auth\User as Authenticatable;
    
    class User extends Authenticatable
    {
        use Notifiable;
    
        /**
         * Route notifications for the Slack channel.
         *
         * @param  \Illuminate\Notifications\Notification  $notification
         * @return string
         */
        public function routeNotificationForSlack($notification)
        {
            return 'https://hooks.slack.com/services/...';
        }
    }

    本地化通知

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

    要实现这一点, Illuminate\Notifications\Notification 类提供了一个 locale 方法来设置所需的语言。在格式化通知时,应用程序将更改为此语言设置,然后在格式化完成后还原为以前的语言设置:

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

    多重通知的本地化也可通过 Notification Facade 实现:

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

    有些情况下,应用程序保存了每个用户的首选语言区域设置。通过在模型上实现 HasLocalePreference 契约,可以指定 Laravel 在发送通知时使用用户保存的首选语言设置:

    use Illuminate\Contracts\Translation\HasLocalePreference;
    
    class User extends Model implements HasLocalePreference
    {
        /**
         * Get the user's preferred locale.
         *
         * @return string
         */
        public function preferredLocale()
        {
            return $this->locale;
        }
    }

    实现接口后,Laravel 将在向模型发送通知和邮件时自动使用首选区域设置。因此,使用此接口时不需要调用 locale 方法:

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

    通知事件

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

    /**
     * The event listener mappings for the application.
     *
     * @var array
     */
    protected $listen = [
        'Illuminate\Notifications\Events\NotificationSent' => [
            'App\Listeners\LogNotification',
        ],
    ];

    {提示} 在 EventServiceProvider 中注册监听器之后,使用 Artisan 命令 event:generate 可以快速生成监听器类。

    在事件监听器中,可以访问事件的 notifiablenotificationchannel 属性了解通知接收者和通知本身的更多信息:

    /**
     * Handle the event.
     *
     * @param  NotificationSent  $event
     * @return void
     */
    public function handle(NotificationSent $event)
    {
        // $event->channel
        // $event->notifiable
        // $event->notification
        // $event->response
    }

    自定义通道

    Laravel 为我们提供了多种通知通道,但是尝试编写自定义通道驱动以通过其他通道发送通知,也很简单。首先定义一个包含 send 方法的类,该方法接收两个参数: $notifiable$notification:

    <?php
    
    namespace App\Channels;
    
    use Illuminate\Notifications\Notification;
    
    class VoiceChannel
    {
        /**
         * 发送指定的通知.
         *
         * @param  mixed  $notifiable
         * @param  \Illuminate\Notifications\Notification  $notification
         * @return void
         */
        public function send($notifiable, Notification $notification)
        {
            $message = $notification->toVoice($notifiable);
    
            // Send notification to the $notifiable instance...
        }
    }
    <?php
    
    namespace App\Notifications;
    
    use Illuminate\Bus\Queueable;
    use App\Channels\VoiceChannel;
    use App\Channels\Messages\VoiceMessage;
    use Illuminate\Notifications\Notification;
    use Illuminate\Contracts\Queue\ShouldQueue;
    
    class InvoicePaid extends Notification
    {
        use Queueable;
    
        /**
         * 获取通知通道.
         *
         * @param  mixed  $notifiable
         * @return array|string
         */
        public function via($notifiable)
        {
            return [VoiceChannel::class];
        }
    
        /**
         * 获取语音表示的通知.
         *
         * @param  mixed  $notifiable
         * @return VoiceMessage
         */
        public function toVoice($notifiable)
        {
            // ...
        }
    }

    本文章首发在 LearnKu.com 网站上。