Laravel 的消息通知系统
简介
除了 发送邮件,Laravel 还支持通过多种频道发送通知,包括邮件、短信(通过 Nexmo)以及 Slack 。通知还能存到数据库,这样就能在网页界面上显示了。
通常情况下,通知应该是简短、有信息量的消息来通知用户你的应用发生了什么。举例来说,如果你在编写一个在线交易应用,你应该会通过邮件和短信频道来给用户发送一条 「账单已付」 的通知。
创建 通知
Laravel 中一条通知就是一个类(通常存在 app/Notifications
文件夹里)。看不到的话不要担心,运行一下 make:notification
命令就能创建了:
php artisan make:notification InvoicePaid
这个命令会在 app/Notifications
目录下生成一个新的通知类。这个类包含 via
方法和几个消息构建方法(比如 toMail
或 toDatabase
),它们会针对指定的渠道把通知转换过为对应的消息。
发送通知
使用 Notifiable Trait
通知可以通过两种方法发送: Notifiable
trait 的 notify
方法或 Notification
facade 。首先,让我们探索使用 trait :
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
}
默认的 App\User
模型中使用了这个 trait,它包含着一个可以用来发通知的方法:notify
。 notify
方法需要一个通知实例做参数:
use App\Notifications\InvoicePaid;
$user->notify(new InvoicePaid($invoice));
记住,你可以在任意模型中使用 Illuminate\Notifications\Notifiable
trait,而不仅仅是在 User
模型中。
使用 Notification Facade
另外,你可以通过 Notification
facade 来发送通知。它主要用在当你给多个可接收通知的实体发送通知的时候,比如给用户集合发通知。要用 facade 发送通知的话,要把可接收通知的实体和通知的实例传递给 send
方法:
Notification::send($users, new InvoicePaid($invoice));
指定发送频道
每个通知类都有个 via
方法,它决定了通知在哪个频道上发送。开箱即用的通知频道有 mail
, database
, broadcast
, nexmo
, 和 slack
。
如果你想用其他的频道比如 Telegram 或者 Pusher ,可以去看下社区驱动的 Laravel 通知频道网站 。
via
方法受到一个 $notifiable
实例,它是接收通知的类实例。你可以用 $notifiable
来决定通知用哪个频道来发送:
/**
* 获取通知发送频道
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return $notifiable->prefers_sms ? ['nexmo'] : ['mail', 'database'];
}
队列化通知
在队列化通知前你需要配置队列,并 运行队列处理器。
发送通知可能会花很长时间,尤其是发送频道需要调用外部 API 的时候。要加速应用响应的话,可以通过添加 ShouldQueue
接口和 Queueable
trait 把通知加入队列。它们两个在使用 make:notification
命令来生成通知文件的时候就已经被导入了,所以你只需要添加到你的通知类就行了:
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
class InvoicePaid extends Notification implements ShouldQueue
{
use Queueable;
// ...
}
一旦加入 ShouldQueue
接口,你就能像平常那样发送通知了。Laravel 会检测 ShouldQueue
接口并自动将通知的发送放入队列中。
$user->notify(new InvoicePaid($invoice));
如果你想延迟发送,你可以通过 delay
方法来链式操作你的通知实例:
$when = Carbon::now()->addMinutes(10);
$user->notify((new InvoicePaid($invoice))->delay($when));