支持mail
sms
easysms
database
等驱动
发送手机验证码
发送验证邮件,找回密码邮件 订单状态变更
站内消息通知
...
composer require yzh52521/think-notification
通常每个通知都由一个存储在 app/notifications 目录下的一个类表示。如果在你的应用中没有看到这个目录,不要担心,当运行 make:notification 命令时它将为您创建:
php think make:notification InvoicePaid
这个命令会在 app/notifications 目录下生成一个新的通知类。每个通知类都包含一个 channels 方法以及一个或多个消息构建的方法比如 toMail 或 toDatabase,它们会针对特定的渠道把通知转换为对应的消息。
使用 Notifiable Trait
通知可以通过两种方式发送: 使用 Notifiable 特性的 notify 方法或使用 Notification 门面
<?php
namespace app\model;
use yzh52521\notification\Notifiable;
class User
{
use Notifiable;
}
此 notify 方法需要接收一个通知实例参数:
use app\notification\InvoicePaid;
$user->notify(new InvoicePaid($invoice));
请记住,你可以在任何模型中使用 Notifiable trait。而不仅仅是在 User 模型中。
另外,你可以通过 Notification facade 来发送通知,它主要用在当你需要给多个可接收通知的实体发送的时候,比如给用户集合发送通知。使用 Facade 发送通知的话,要把可接收通知实例和通知实例传递给 send 方法:
use yzh52521\facade\Notification;
Notification::send($users, new InvoicePaid($invoice));
您也可以使用 sendNow 方法立即发送通知。即使通知实现了 ShouldQueue 接口,该方法也会立即发送通知:
Notification::sendNow($developers, new DeploymentCompleted($deployment));
每个通知类都有一个 channels 方法,用于确定将在哪些通道上传递通知。通知可以在 mail、database、sms、easysms 频道上发送。
channels 方法接收一个 $notifiable 实例,这个实例将是通知实际发送到的类的实例。你可以用 $notifiable 来决定这个通知用哪些频道来发送:
/**
* 获取通知发送频道
*
* @param mixed $notifiable
* @return array
*/
public function channels($notifiable)
{
return $notifiable->prefers_sms ? ['sendcloud'] : ['mail', 'database'];
}
注意:使用通知队列前需要配置队列并 开启一个队列任务。
发送通知可能是耗时的,尤其是通道需要调用额外的 API 来传输通知。为了加速应用的响应时间,可以将通知推送到队列中异步发送,而要实现推送通知到队列,可以让对应通知类实现 ShouldQueue 。如果通知类是通过 make:notification 命令生成的,你可以快速将它们添加到通知类:
<?php
namespace app\notifications;
use think\queue\ShouldQueue;
use yzh52521\Notification;
use yzh52521\notification\message\Mail;
use yzh52521\notification\Notifiable;
class InvoicePaid extends Notification implements ShouldQueue
{
// ...
}
一旦 ShouldQueue 接口被添加到您的通知中,您就可以像往常一样发送通知。 Thinkphp 将检测类上的 ShouldQueue 接口并自动将通知的传递排队:
$user->notify(new InvoicePaid($invoice));
如果您想延迟通知的传递,您可以设置 delay:
public function __construct(Order $order)
{
$this->order = $order;
$this->delay =5;
}
自定义通知队列连接: 默认情况下,排队通知将使用应用程序的默认队列连接进行排队。如果您想为特定通知指定一个不同的连接,您可以在通知类上定义一个 $connection 属性:
public function __construct(Order $order)
{
$this->order = $order;
public $connection = 'redis';
$this->delay =5;
}
composer require yzh52521/think-mailer
格式化邮件信息
如果通知支持作为电子邮件发送,您应该在通知类上定义一个 toMail 方法。 此方法将接收一个 $notifiable 实体并应返回一个 yzh52521\notification\message\Mail 实例。
Mail 类包含一些简单的方法来帮助您构建事务性电子邮件消息。 邮件消息可能包含文本行以及「动作的调用」。让我们看一个示例 toMail 方法:
/**
* 获取通知的邮件描述。
*
* @param mixed $notifiable
* @return \yzh52521\notification\messages\Mail
*/
public function toMail($notifiable)
{
$url = url('/invoice/'.$this->invoice->id);
return (new Mail)
->greeting('Hello!')
->line('你的一张发票已经付款了!')
->action('查看发票', $url)
->line('感谢您使用我们的应用程序!');
}
自定义模板 使用 view() 不需要使用 greeting 、 line 、action 等参数 在 view 第二个参数传递
public function toMail($notifiable)
{
return (new Mail)
->to($to)
->subject('找回密码')
->view('emails.name', ['invoice' => $this->invoice]);
}
自定义发件人 默认情况下, 发件人地址在 config/mail.php 配置文件中定义。但是,您可以使用 from 方法指定特定通知的发件人地址:
public function toMail($notifiable)
{
return (new Mail)
->from('barrett@example.com', 'Barrett Blair')
->line('...');
}
其他用法 参考 yzh52521/think-mailer
必要条件 database 通知通道将通知信息存储在数据库表中。此表将包含通知类型等信息以及描述通知的 JSON 数据结构。 使用的模型必须 use HasDatabaseNotification Trait
您可以查询该表以在应用程序的用户界面中显示通知。但是,在您这样做之前,您需要创建一个数据库表来保存您的通知。您可以使用 notifications:table 命令生成具有正确表模式的 migration:
php think notification:table
php think migrate:run
如果通知支持存储在数据库表中,则应在通知类上定义 toDatabase 方法。这个方法将接收一个 $notifiable 实体并且应该返回一个普通的 PHP 数组。 返回的数组将被编码为 JSON 并存储在 notifications 表的 data 列中。让我们看一个示例 toDatabase 方法:
public function toDatabase($notifiable)
{
return [
'invoice_id' => $this->invoice->id,
'amount' => $this->invoice->amount,
];
}
访问通知
一旦通知存储在数据库中,您需要一种方便的方式从您的通知实体访问它们. 必须实现 model 之前的关联关系
$user = app\model\User::find(1);
foreach ($user->notifications as $notification) {
echo $notification->notification_type;
}
如果您只想检索「未读」通知,可以使用 unreadNotifications 关系。同样,这些通知将按 create_time 时间戳排序,最近的通知位于集合的开头:
$user = app\model\User::find(1);
foreach ($user->unreadNotifications as $notification) {
echo $notification->notification_type;
}
将通知标记为已读# 通常,您希望在用户查看通知时将其标记为 “已读”。 yzh52521\notification\Notifiable trait 提供了 markAsRead 方法,它更新通知数据库记录中的 read_time 列:
$user = app\model\User::find(1);
foreach ($user->unreadNotifications as $notification) {
$notification->markAsRead();
}
但是,您可以直接在通知集合上使用 markAsRead 方法,而不是循环遍历每个通知:
$user->unreadNotifications->markAsRead();
您还可以使用批量更新查询将所有通知标记为已读,而无需从数据库中检索它们:
$user = app\model\User::find(1);
$user->unreadNotifications()->update(['read_time' => now()]);
您可以 delete 通知以将它们从表中完全删除:
$user->notifications()->delete();
SMS 通知由 Sendcloud 提供支持
必要条件 $user 发件人 $key sendcloud 申请的key
依赖扩展
composer require yzh52521/easyhttp
public function toSendcloud($notifiable)
{
return (new Sendcloud($user,$key))
->data('Your SMS message content');
}
格式化短信通知
public function toSendcloud($notifiable)
{
return (new Sendcloud($user,$key))
->data('Your SMS message content');
}
收件人 to()
public function toSendcloud($notifiable)
{
return (new Sendcloud($user,$key))
->to('15556666666')
->data('Your SMS message content');
}
短信模版 template()
public function toSendcloud($notifiable)
{
return (new Sendcloud($user,$key))
->to('15556666666')
->template('40438')
->data('Your SMS message content');
}
设置为彩信 isMultimedia()
public function toSendcloud($notifiable)
{
return (new Sendcloud($user,$key))
->to('15556666666')
->isMultimedia()
->data('Your SMS message content');
}
设为语音短信 isVoice()
public function toSendcloud($notifiable)
{
return (new Sendcloud($user,$key))
->to('15556666666')
->isVoice()
->data('Your SMS message content');
}
依赖扩展 yzh52521/think-sms
composer require yzh52521/think-sms
sms 配置
config/sms.php
$config = [
// HTTP 请求的超时时间(秒)
'timeout' => 5.0,
// 默认发送配置
'default' => [
// 网关调用策略,默认:顺序调用
'strategy' => \Overtrue\EasySms\Strategies\OrderStrategy::class,
// 默认可用的发送网关
'gateways' => [
'aliyun',
],
],
// 可用的网关配置
'gateways' => [
'errorlog' => [
'file' => '/tmp/easy-sms.log',
],
'aliyun' => [
'access_key_id' => '',
'access_key_secret' => '',
'sign_name' => '',
],
//...
],
];
创建通知
namespace app\notification;
use yzh52521\notification\message\Easysms;
class ValidateCode extends Notification
{
public function channels($notifiable)
{
return ['easysms'];
}
public function toEasysms($notifiable)
{
return ( new Easysms )
->to('13188888888')
->template('SMS_001')
->content('您的验证码{$code},该验证码5分钟内有效,请勿泄漏于他人!')
->data(['code' =>6379]);
}
}
think-notification 提供了一些通知频道,但你可能想编写自己的驱动程序,以通过其他频道传递通知。要开始,定义一个包含 send 方法的类。该方法应接收两个参数:$notifiable 和 $notification 在 send 方法中,你可以调用通知上的方法来检索一个由你的频道理解的消息对象,然后按照你希望的方式将通知发送给 $notifiable 实例:
namespace app\notification;
use yzh52521\notification\Notifiable;
use yzh52521\notification\Channel;
use yzh52521\Notification;
class VoiceChannel extends Channel
{
/**
* 发送给定的通知
* @param Notifiable $notifiable
* @param Notification $notification
* @return mixed
*/
public function send($notifiable, Notification $notification): void
{
$message = $notification->toVoice($notifiable);
// 将通知发送给 $notifiable 实例...
}
}
一旦你定义了你的通知频道类,你可以从你的任何通知的 channels 方法返回该类的名称。在这个例子中,你的通知的 toVoice 方法可以返回你选择来表示语音消息的任何对象。例如,你可以定义自己的 VoiceMessage 类来表示这些消息:
use yzh52521\Notification;
use yzh52521\notification\Notifiable;
class InvoicePaid extends Notification
{
/**
* 获取通知频道
* @param Notifiable $notifiable
*/
public function channels( $notifiable)
{
return VoiceChannel::class;
}
/**
* 获取通知的语音表示形式
* @param Notifiable $notifiable
*/
public function toVoice($notifiable): VoiceMessage
{
// ...
}
}
自定义 VoiceMessage
class VoiceMessage
{
// ...
}