通知
简介
除了支持发送邮件之外,Laravel 还支持通过多种传输通道发送通知,这些通道包括邮件、短信(通过 Nexmo)以及 Slack 等。通知可以存储在数据库以便后续在 Web 界面中显示。
通常,通知都是很短的、用于告知用户应用中所发生事件的消息。例如,如果你在开发一个计费应用,则需要通过邮件或短信等渠道给用户发送“账单支付”通知。
创建通知
在 Laravel 中,每个通知都以单独类的形式存在(通常存放在 app/Notifications
目录),如果在应用中没看到这个目录,别担心,它将会在你运行 Artisan 命令 make:notification
的时候自动创建:
php artisan make:notification InvoicePaid
该命令会在 app/Notifications
目录下生成一个新的通知类 InvoicePaid
,每个通知类都包含一个 via
方法以及多个消息构建方法(如 toMail
或 toDatabase
),这些消息构建方法用于将通知转化成为特定渠道优化的消息。默认生成的模板代码如下:
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class InvoicePaid 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('The introduction to the notification.')
->action('Notification Action', url('/'))
->line('Thank you for using our application!');
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}
发送通知
使用 Notifiable Trait
通知可以通过两种方式发送:使用 Notifiable
trait 提供的 notify
方法或者使用 Notification
门面。首先,我们使用 Notifiable
trait 来测试:
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
}
该 trait 被默认的 App\Models\User
模型使用并提供一个可用于发送通知的方法:notify
。notify
方法接收一个通知实例:
use App\Notifications\InvoicePaid;
$user->notify(new InvoicePaid($invoice));
注:你可以在任何模型中使用
Illuminate\Notifications\Notifiable
trait,不限于只在User
模型中使用。
使用 Notification 门面
作为替代方案,还可以通过 Notification
门面发送通知。这在你需要发送通知给多个用户的时候很有用,要使用这个门面发送通知,需要将所有被通知用户和通知实例传递给 send
方法:
Notification::send($users, new InvoicePaid($invoice));
指定传输通道
每个通知类都有一个 via
方法用于决定通知通过何种通道传输,Laravel 开箱支持 mail
、 database
、 broadcast
、 nexmo
以及 slack
通道。
注:如果你想要使用其他传输通道,比如 Telegram 或 Pusher,参考社区提供的驱动:Laravel 通知通道网站。
via
方法接收一个 $notifiable
实例,用于指定通知被发送到的类实例。你可以使用 $notifiable
来判断通知通过何种通道传输:
/**
* 获取通知的传递渠道.
*
* @param mixed $notifiable
* @return array
* @translator laravelacademy.org
*/
public function via($notifiable)
{
return $notifiable->prefers_sms ? ['nexmo'] : ['mail', 'database'];
}
通知队列
注:使用通知队列前需要配置队列并开启一个队列任务。
发送通知可能是耗时的,尤其是通道需要调用额外的 API 来传输通知。为了加速应用的响应时间,可以将通知推送到队列中异步发送,而要实现推送通知到队列,可以让对应通知类实现 ShouldQueue
接口并使用 Queueable
trait。如果通知类是通过 make:notification
命令生成的,那么该接口和 trait 已经默认导入,你可以快速将它们添加到通知类:
<?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));
自定义通知通道队列
如果你想要为通知功能支持的每个通知通道指定一个特定的队列,可以在通知类中定义 viaQueues
方法来实现,该方法会返回通道名/队列名键值对数组:
/**
* Determine which queues should be used for each notification channel.
*
* @return array
*/
public function viaQueues()
{
return [
'mail' => 'mail-queue',
'slack' => 'slack-queue',
];
}
按需通知
有时候你可能需要发送通知给某个用户,但是该用户不存在于应用的用户系统中,要实现这一目的,我们使用 Notification::route
方法在发送同之前指定特别的通知路由:
Notification::route('mail', 'taylor@laravel.com')
->route('nexmo', '5555555555')
->route('slack', 'https://hooks.slack.com/services/...')
->notify(new InvoicePaid($invoice));
邮件通知
格式化邮件消息
如果通知支持以邮件方式发送,你需要在通知类上定义一个 toMail
方法。该方法会接收一个 $notifiable
实体并返回 Illuminate\Notifications\Messages\MailMessage
实例。邮件消息可以包含多行文本以及对动作的调用,让我们来看一个 toMail
方法的示例:
/**
* 获取通知对应的邮件.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
$url = url('/invoice/'.$this->invoice->id);
return (new MailMessage)
->greeting('Hello!')
->line('One of your invoices has been paid!')
->action('View Invoice', $url)
->line('Thank you for using our application!');
}
注:注意到我们在
message
方法中使用了$this->invoice->id
,你可以传递任何通知生成消息所需要的数据到通知的构造器。
在这个例子中,我们注册了一条问候、一行文本、对动作的调用以及另一行文本。MailMessage
对象提供的这些方法让格式化短小的事务邮件变得简单快捷。mail
通道会将消息组件转化为美观的、响应式的、带有纯文本副本的 HTML 邮件模板。下面是一个通过 mail
通道生成的邮件示例:
注:发送邮件通知时,确保在配置文件
config/app.php
中设置了name
的值,该值将会用在邮件通知消息的头部和尾部。
其他通知格式化选项
除了在通知类中定义多行文本之外,你还可以使用 view
方法来指定一个自定义的、用于渲染通知邮件的模板:
/**
* 获取通知邮件.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
* @translator laravelacademy.org
*/
public function toMail($notifiable)
{
return (new MailMessage)->view(
'emails.name', ['invoice' => $this->invoice]
);
}
在 MailMessage
的 view
方法中,你可以通过第一个数组参数的第二个元素为邮件消息指定一个纯文本视图,这个数组参数中包含的都是邮件消息视图模板:
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)->view(
['emails.name.html', 'emails.name.plain'],
['invoice' => $this->invoice]
);
}
此外,你可以从 toMail
方法中返回一个可邮寄对象:
use App\Mail\InvoicePaid as Mailable;
/**
* 获取通知邮件
*
* @param mixed $notifiable
* @return Mailable
*/
public function toMail($notifiable)
{
return new Mailable($this->invoice)->to($this->user->email);
}
错误消息
一些通知会告知用户错误信息,例如失败的订单支付。你可以在构建消息的时候调用 error
方法来指示该邮件消息表示错误信息。在邮件消息中使用 error
方法时,动作按钮将会变成红色:
/**
* 获取通知邮件.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Message
*/
public function toMail($notifiable)
{
return (new MailMessage)
->error()
->subject('Notification Subject')
->line('...');
}
自定义发送人
默认情况下,邮件的发送人/发送邮箱定义在配置文件 config/mail.php
中。不过,你可以使用 from
方法为特定通知指定发送邮箱:
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->from('test@example.com', 'Example')
->line('...');
}
自定义收件人
通过 mail
通道发送通知时,通知系统会自动在被通知实体上查找 email
属性,你可以通过在该实体上定义一个 routeNotificationForMail
来自定义使用哪个邮箱地址发送通知:
<?php
namespace App\Models;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* Route notifications for the mail channel.
*
* @param \Illuminate\Notifications\Notification $notification
* @return array|string
*/
public function routeNotificationForMail($notification)
{
// Return email address only...
return $this->email_address;
// Return name and email address...
return [$this->email_address => $this->name];
}
}
自定义主题
默认情况下,邮件的主题就是格式为“标题风格”的通知类名,因此,如果通知类被命名为 InvoicePaid
,邮件的主题就是 Invoice Paid
,如果你想要为消息指定明确的主题,可以在构建消息的时候调用 subject
方法:
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->subject('Notification Subject')
->line('...');
}
自定义邮件驱动
默认情况下,邮件通知使用定义在 config/mail.php
配置文件中的默认邮件驱动进行发送操作。不过,你也可以在构建邮件消息时通过调用 mailer
方法在运行时指定使用其它邮件驱动:
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->mailer('postmark')
->line('...');
}
自定义模板
你可以通过发布通知扩展包的资源来修改邮件通知所使用的 HTML 和纯文本模板。运行完下面这个命令之后,邮件通知模板将会存放到 resources/views/vendor/notifications
目录:
php artisan vendor:publish --tag=laravel-notifications
预览邮件通知
设计邮件通知模板时,在浏览器中像 Blade 模板那样快速预览渲染的邮件消息很方便,为此,Laravel 允许你直接从路由闭包或控制器中返回任意通过邮件通知生成的邮件消息。当 MailMessage
被返回时,它将会被渲染并显示在浏览器中,以便你快速预览和调整,而不必真的发送一封邮件:
Route::get('mail', function () {
$invoice = App\Models\Invoice::find(1);
return (new App\Notifications\InvoicePaid($invoice))
->toMail($invoice->user);
});
Markdown 邮件通知
Markdown 邮件通知允许你利用邮件通知的预置模板,从而让你可以自由编写更长、更具个性化的消息。因为这些消息以 Markdown 格式编写,Laravel 还可以为它们渲染出高颜值、响应式的 HTML 模板,同时自动生成纯文本的副本。
生成消息
要生成带有相应 Markdown 模板的通知,可以在使用 Artisan 命令 make:notification
时带上 --markdown
选项:
php artisan make:notification InvoicePaid --markdown=mail.invoice.paid
和其他邮件通知一样,使用 Markdown 模板的通知类也要定义一个 toMail
方法。不过,你可以使用 markdown
方法取代构造通知的 line
和 action
方法来指定要使用的 Markdown 模板名称:
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
* @translator xueyuanjun.com
*/
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
,支持的颜色有 blude
,green
和 red
。你可以添加任意数量的按钮组件到消息中:
@component('mail::button', ['url' => $url, 'color' => 'green'])
View Invoice
@endcomponent
面板组件
面板组件将给定的文字区块渲染到一个面板中,并且有一个淡淡的背景色与周围的消息区分开。适用于需要引起注意的文字区块:
@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
目录包含 html
和 markdown
目录,每个子目录中又包含各自的所有有效组件。你可以按照自己的喜好自由编辑这些组件。
自定义 CSS
导出组件之后,resources/views/vendor/mail/html/themes
目录将会包含一个默认的 default.css
文件,你可以在这个文件中自定义 CSS,这样 Markdown 通知的 HTML 样式就会自动调整。
如果你想要为 Markdown 组件构建全新的主题,只需在 html/themes
目录中编写一个新的 CSS 文件并修改 mail
配置文件的 theme
选项即可。
要为独立的通知自定义主题,可以在构建通知的邮件消息时调用 theme
方法,该方法接收发送通知时使用的主题名称作为参数:
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->theme('invoice')
->subject('Invoice Paid')
->markdown('mail.invoice.paid', ['url' => $url]);
}
数据库通知
预备知识
database
通知通道会在数据表中存储通知信息,该表包含诸如通知类型以及用于描述通知的自定义 JSON 数据之类的信息。
你可以在用户界面中查询这个数据表来展示通知,不过,在此之前,需要创建数据表来保存信息,你可以使用 notifications:table
命令来生成迁移文件然后以此生成相应数据表:
php artisan notifications:table
php artisan migrate
格式化数据库通知
如果一个通知支持存放在数据表,则需要在通知类中定义 toDatabase
或 toArray
方法,该方法接收一个 $notifiable
实体并返回原生的 PHP 数组。返回的数组会被编码为 JSON 格式然后存放到 notifications
表的 data
字段。让我们来看一个 toArray
方法的例子:
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
'invoice_id' => $this->invoice->id,
'amount' => $this->invoice->amount,
];
}
toDatabase
Vs. toArray
toArray
方法还被 broadcast
通道用来判断广播什么数据到 JavaScript 客户端,如果你想要为 database
和 broadcast
通道提供两种不同的数组表示,则需要定义一个 toDatabase
方法来取代 toArray
方法。
访问通知
通知被存放到数据表之后,需要在被通知实体中有一个便捷的方式来访问它们。Laravel 默认提供的 App\Models\User
模型引入的 Illuminate\Notifications\Notifiable
Trait 包含了返回实体对应通知的 Eloquent 关联关系方法 notifications
,要获取这些通知,可以像访问其它 Eloquent 关联关系一样访问该关联方法,默认情况下,通知按照 created_at
时间戳排序:
$user = App\Models\User::find(1);
foreach ($user->notifications as $notification) {
echo $notification->type;
}
如果你只想获取“未读”通知,可使用关联关系 unreadNotifications
,同样,这些通知也按照 created_at
时间戳排序:
$user = App\Models\User::find(1);
foreach ($user->unreadNotifications as $notification) {
echo $notification->type;
}
注:要想从 JavaScript 客户端访问通知,需要在应用中定义一个通知控制器为指定被通知实体(比如当前用户)返回通知,然后从 JavaScript 客户端发送一个 HTTP 请求到控制器对应 URI。
标记通知为已读
一般情况下,我们会将用户浏览过的通知标记为已读,Illuminate\Notifications\Notifiable
Trait 提供了一个 markAsRead
方法,用于更新对应通知数据库纪录上的 read_at
字段:
$user = App\Models\User::find(1);
foreach ($user->unreadNotifications as $notification) {
$notification->markAsRead();
}
如果觉得循环遍历每个通知太麻烦,可以直接在通知集合上调用 markAsRead
方法:
$user->unreadNotifications->markAsRead();
还可以使用批量更新方式标记通知为已读,无需先从数据库获取通知:
$user = App\Models\User::find(1);
$user->unreadNotifications()->update(['read_at' => now()]);
当然,你也可以通过 delete
方法从数据库中移除这些通知:
$user->notifications()->delete();
广播通知
预备知识
在进行广播通知之前,需要配置并了解事件广播服务,事件广播为 JavaScript 客户端响应服务端触发的事件铺平了道路。
格式化广播通知
broadcast
通道广播通知使用了 Laravel 的事件广播服务,从而允许 JavaScript 客户端实时捕获通知。如果通知支持广播,则需要在通知类上定义 toBroadcast
方法,该方法接收一个 $notifiable
实体并返回一个 BroadcastMessage
实例,返回的数组会编码成 JSON 格式然后广播到 JavaScript 客户端。让我们来看一个 toBroadcast
方法的示例:
use Illuminate\Notifications\Messages\BroadcastMessage;
/**
* Get the broadcastable representation of the notification.
*
* @param mixed $notifiable
* @return BroadcastMessage
*/
public function toBroadcast($notifiable)
{
return new BroadcastMessage([
'invoice_id' => $this->invoice->id,
'amount' => $this->invoice->amount,
]);
}
广播队列配置
所有广播通知都会被推送到广播队列,如果你想要配置广播操作队列的连接或名称,可以使用 BroadcastMessage
的 onConnection
和 onQueue
方法:
return new BroadcastMessage($data)
->onConnection('sqs')
->onQueue('broadcasts');
自定义通知类型
除了指定的数据之外,广播通知还包含一个 type
字段,用于包含通知的完整类名。如果你想要自定义提供给 JavaScript 客户端的通知 type
,可以在通知类中定义 broadcastType
方法来实现:
use Illuminate\Notifications\Messages\BroadcastMessage;
/**
* Get the type of the notification being broadcast.
*
* @return string
*/
public function broadcastType()
{
return 'broadcast.message';
}
监听通知
通知将会以格式化为 {notifiable}.{id}
的形式在私有频道上广播,因此,如果你要发送通知到 ID 为 1
的 App\User
实例,那么该通知将会在私有频道 App.User.1
上进行广播,如果使用了Laravel Echo,可以使用辅助函数 notification
轻松在某个频道上监听通知:
Echo.private('App.User.' + userId)
.notification((notification) => {
console.log(notification.type);
});
自定义通知通道
如果你想要自定义被通知实体在那个通道上接收广播通知,可以在被通知实体上定义一个 receivesBroadcastNotificationsOn
方法:
<?php
namespace App\Models;
use Illuminate\Notifications\Notifiable;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* 用户接收广播通知的通道.
*
* @return array
*/
public function receivesBroadcastNotificationsOn()
{
return 'users.'.$this->id;
}
}
短信(SMS)通知
预备知识
Laravel 基于 Nexmo 发送短信通知,在使用Nexmo 发送通知前,需要安装对应 Composer 依赖包 laravel/nexmo-notification-channel
:
composer require laravel/nexmo-notification-channel
安装上述依赖的同时也会安装 nexmo/laravel 扩展包,该扩展包会包含自己的配置文件,你可以使用 NEXMO_KEY
和 NEXMO_SECRET
环境变量来设置 Nexmo 的公钥和私钥。
接下来,需要在配置文件 config/services.php
中添加相应配置,例如:
'nexmo' => [
'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');
}
格式化验证码通知
Laravel 还支持发送验证码通知,对应的消息模板可以在 Nexmo 账户中预定义,你可以指定通知类型(alert
、2fa
或者 marketing
),以及填充模板的自定义值:
/**
* Get the Nexmo / Shortcode representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toShortcode($notifiable)
{
return [
'type' => 'alert',
'custom' => [
'code' => 'ABC123',
];
];
}
注:和短信通知路由一样,你需要在通知模型中实现
routeNotificationForShortcode
方法。
Unicode 内容
如果你的短信消息包含 Unicode 字符,需要在构造 NexmoMessage
实例时调用unicode
方法:
/**
* Get the Nexmo / SMS representation of the notification.
*
* @param mixed $notifiable
* @return NexmoMessage
*/
public function toNexmo($notifiable)
{
return (new NexmoMessage)
->content('Your unicode message')
->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\Models;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* Route notifications for the Nexmo channel.
*
* @return string
*/
public function routeNotificationForNexmo()
{
return $this->phone_number;
}
}
Slack 通知
预备知识
在通过 Slack 发送通知前,必须通过 Composer 安装对应的通知渠道扩展包:
composer require laravel/slack-notification-channel
此外,你还要为 Slack 组配置一个「Incoming Webhook」集成。该集成会在你进行 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,最终创建的消息如下:
自定义发送者 & 接收者
你可以使用 from
和 to
方法自定义发送者和接收者,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 消息:
Markdown 附件内容
如果一些附件字段包含 Markdown,可以使用 markdown
方法来构建 Slack 用以解析并显示以 Markdown 格式编写的附件字段,该方法支持的值包括 pretext
、text
、/ 或 fields
。想要了解更多关于 Slack 格式化的信息,查看 Slack API 文档:
/**
* 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\Models;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* Route notifications for the Slack channel.
*
* @return string
*/
public function routeNotificationForSlack()
{
return $this->slack_webhook_url;
}
}
本地化通知
和邮件类似,Laravel 允许你通过本地化设置语言而非当前默认语言发送通知,甚至在通知队列中也能记住本地化设置。
为了实现这个功能,Illuminate\Notifications\Notification
类提供了一个 locale
方法用于设置期望的语言。应用会在通知被格式化的时候切换到此次设置的本地化语言,格式化完成后,再切换回之前设置的本地化语言:
$user->notify((new InvoicePaid($invoice))->locale('es'));
还可以通过 Notification
门面同时为多个通知实体进行本地化语言设置:
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
快速生成监听器类。
在事件监听器中,可以访问事件的 notifiable
、 notification
和 channel
属性了解通知接收者和通知本身的更多信息:
/**
* 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);
// 发送通知到$notifiable实例...
}
}
通知通道类被定义后,就可以在应用中通过 via
方法返回类名:
<?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];
}
/**
* Get the voice representation of the notification.
*
* @param mixed $notifiable
* @return VoiceMessage
*/
public function toVoice($notifiable)
{
// ...
}
}
3 条评论
遗漏了 数据库事务成功提交后再放到通知队列的内容
这个生成的表到数据库的主键是uuid的形式,可以换成自增id吗
找到方法了,只能重写或者改vender包里的buildPayload方法