percipioglobal / craft-notifications
通过多种交付渠道发送通知,包括邮件和Slack。通知也可以存储在数据库中,以便在您的网页界面中显示。
Requires
- php: ^8.0.2
- craftcms/cms: ^4.0.0-beta.1
- guzzlehttp/guzzle: ^7.0
- nesbot/carbon: ^2.19
Requires (Dev)
- craftcms/phpstan: dev-main
- v4.x-dev
- 4.1.2
- 4.1.1
- 4.1.0
- 4.0.0
- 4.0.0-RC1
- v1.x-dev
- 1.2.3
- 1.2.2
- 1.2.1
- 1.2.0
- 1.1.6
- 1.1.5.2
- 1.1.4
- 1.1.3
- 1.1.1
- 1.1.0
- 1.0.6
- 1.0.5
- 1.0.4
- 1.0.1
- 1.0.0
- dev-v4-develop
- dev-dependabot/composer/guzzlehttp/psr7-2.5.0
- dev-renovate/configure
- dev-v1-develop
- dev-master
- dev-dependabot/composer/tightenco/collect-tw-7.12
- dev-dependabot/composer/ramsey/uuid-tw-4.0
- dev-develop
This package is auto-updated.
Last update: 2024-04-12 13:21:40 UTC
README
Craft CMS 3.x 的通知插件
通过多种交付渠道发送通知,包括邮件和Slack。通知也可以存储在数据库中,以便在您的网页界面中显示。
支持开源。买啤酒。
此插件采用MIT许可,这意味着它是一项完全免费的开源软件,您可以随意使用。如果您在使用它并想支持开发,请在Beerpay上为我买一杯啤酒!
要求
此插件需要Craft CMS 3.1.0或更高版本。
安装
要安装插件,请按照以下说明操作。
-
打开您的终端并转到您的Craft项目
cd /path/to/project
-
然后告诉Composer加载插件
composer require percipioglobal/craft-notifications
-
在控制面板中,转到设置 → 插件,并点击“安装”按钮以安装通知。
-
将
config.php
文件复制到应用程序中的config/notifications.php
。 -
确保通过将以下内容添加到您的
composer.json
并运行composer dump -o
来自动加载通知。
"autoload": {
"psr-4": {
"app\\notifications\\": "./notifications"
}
},
简介
通常,通知应该是简短的信息性消息,通知用户您的应用程序中发生了某事。例如,如果您正在编写账单应用程序,您可能通过电子邮件和短信渠道向用户发送“发票已支付”通知。
创建通知
每个通知都由单个类表示(存储在您的应用程序的notifications
目录中)。您必须手动创建它,或者当您运行notifications/make
命令时,它将为您创建。
./craft notifications/make BlogPostAdded
此命令将在您的notifications
目录中放置一个新的通知类。每个通知类都包含一个via
方法和多个消息构建方法(例如toMail
或toDatabase
),这些方法将通知转换为针对特定渠道优化的消息。
发送通知
通知可以通过两种方式发送,一种是从配置文件在事件触发时发送,另一种是从您自己的插件发送。
首先,让我们看看如何在添加新博客文章时配置发送通知。
<?php return [ 'notifications' => [ [ 'class' => \craft\elements\Entry::class, 'event' => \craft\elements\Entry::EVENT_AFTER_SAVE, 'notification' => \app\notifications\BlogPostAdded::class, ], ], ];
这里我们在Craft的Entry
类的EVENT_AFTER_SAVE
事件上进行监听,这将导致我们每次保存条目时触发通知。
在我们的BlogPostAdded
类中,我们可以使用via
函数来确定是否以及如何发送通知。
/** * Get the notification's delivery channels. * * @return array */ public function via() { $entry = $this->event->sender; if ($entry->section->handle === 'blog' && $this->event->isNew) { return [ 'database' => Craft::$app->getUsers()->getUserByUsernameOrEmail('hello@percipio.london'), ]; } return []; }
我们知道该事件是一个 ElementEvent
,它包含 sender
和 isNew
属性,利用这些信息我们可以确定只有在条目来自 blog
部分,并且是新的条目时,我们才发送通知。
从插件发送通知
从插件中,您可以使用 notificationsService
发送自己的通知。
use percipioglobal\notifications\Notifications; use app\notifications\BlogPostAdded; Notifications::getInstance()->notificationsService->send(new BlogPostAdded());
数据库通知
要将在数据库中保存通知以供稍后检索,请确保您的 via
方法返回包含 User
对象的 database
键。
return [ 'database' => Craft::$app->getUsers()->getUserByUsernameOrEmail('hello@percipio.london'), ];
当使用 database
通知通道时,您的 Notification 类应定义一个 toDatabase
或 toArray
函数。
这可以很简单,例如
public function toDatabase() { return ArrayHelper::toArray($this); }
在模板中从数据库检索通知时,通知将包含这里传递的数据。
检索通知
通知插件提供了一个模板变量来检索通知并标记为已读。
让我们看看如何遍历通知,这会自动使用当前登录用户来查找通知。
{% for notification in craft.notifications.unread %} {# The notification object contains all the data from the toDatabase or toArray function on your notification class #} {% endfor %}
您也可以通过 notificationsService
检索通知。
use percipioglobal\notifications\Notifications; // All unread notifications Notifications::getInstance()->notificationsService->getAllUnread(); // All read notifications Notifications::getInstance()->notificationsService->getAllRead(); // All notifications Notifications::getInstance()->notificationsService->getAll();
标记通知为已读
要标记通知为已读,我们可以使用 Twig 变量或 notificationsService
。此函数期望一个通知数组。
{% for notification in craft.notifications.unread %} {{ craft.notifications.markAsRead(notification) }} {% endfor %}
use percipioglobal\notifications\Notifications; Notifications::getInstance()->notificationsService->markAsRead($notification);
删除已读通知
为了保持数据库整洁,您可以删除超过指定时间框架的已读通知。默认时间设置为 -1 month
。如果您想自定义时间框架,请提供 strtotime PHP 限制内的日期。
./craft notifications/remove-notifications/index --time="-3 months"
邮件通知
要配置发送电子邮件的通知,请确保您的 Notification 类中的 via
方法返回一个具有 mail
的键。
return [ 'mail' => 'hello@percipio.london', ];
如果通知支持作为电子邮件发送,您应在通知类中定义一个 toMail
方法。此方法将接收一个包含您在 via
方法中定义的一切的 $notifiable
对象。
toMail
函数应返回一个 craft\mail\Message
实例。如果您想发送多封电子邮件,也可以返回一个 craft\mail\Message
实例数组。让我们看看一个 toMail
方法的示例
public function toMail($notifiable) { $title = $this->event->sender->title; $message = new Message(); $message->setTo($notifiable); $message->setSubject("A new blogpost was added"); $message->setHtmlBody(" <p>Hey there!</p> <p>A new blogpost was added with the title {$title}</p> "); return $message; }
Slack通知
您需要为您的 Slack 团队配置一个 "Incoming Webhook" 集成。此集成将为您提供可以在定义 via
函数时使用的 URL。
return [ 'slack' => '<YOUR_WEBHOOK_URL>', ];
实现和文档主要基于 Laravel Notifications。
格式化 Slack 通知
如果通知支持作为 Slack 消息发送,您应在通知类中定义一个 toSlack
方法。此方法应返回一个 percipioglobal\notifications\messages\SlackMessage
实例。Slack 消息可以包含文本内容以及一个 "附件",用于格式化额外的文本或字段数组。让我们看看一个基本的 toSlack
示例
/** * Get the Slack representation of the notification. * * @param mixed $notifiable * @return SlackMessage */ public function toSlack() { return (new SlackMessage) ->content('A new blogpost was added!'); }
自定义发送者和接收者
您可以使用 from
和 to
方法来自定义发送者和接收者。from
方法接受用户名和表情符号标识符,而 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'); }
您还可以使用图像作为您的徽标而不是表情符号
/** * Get the Slack representation of the notification. * * @param mixed $notifiable * @return SlackMessage */ public function toSlack($notifiable) { return (new SlackMessage) ->from('Laravel') ->image('https://yoursite.com/favicon.png') ->content('This will display your 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.'); }); }
附件还允许您指定一个应向用户展示的数据数组。给定的数据将以表格格式展示,便于阅读。
/** * 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:', ]); }); }
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']); }); }
通知事件
当发送通知时,会触发两个事件,分别是NotificationsService::EVENT_BEFORE_SEND
和NotificationsService::EVENT_AFTER_SEND
,这两个事件会发送一个percipioglobal\notifications\events\SendEvent
事件。
sendEvent
包含以下属性
/** * @var mixed The notifiable. */ public $notifiable; /** * @var NotificationsRecord The notification about to be sent. */ public $notification; /** * @var string The channel on which the notification is about to be sent. */ public $channel; /** * @var bool Whether we send the notification */ public $sendNotification = true; /** * @var mixed The response after sending the event */ public $response = null;
在监听EVENT_BEFORE_SEND
时,可以更改sendNotification
属性以阻止通知发送。仅当事件为EVENT_AFTER_SEND
时,才会设置response
属性。
自定义渠道
Craft Notifications内置了三个通道(数据库、邮件和Slack),但您可能希望编写自己的驱动程序以通过其他通道发送通知。我们通过提供一个注册新通道的事件来实现这一点,使其变得简单。
让我们看看如何注册一个voice
通道
Event::on( NotificationsService::class, NotificationsService::EVENT_REGISTER_CHANNELS, function (RegisterChannelsEvent $event) { $event->channels[] = [ 'voice' => function () { return new VoiceChannel(); }, ]; } );
您的VoiceChannel
类将如下所示
<?php namespace app\channels; use percipioglobal\notifications\models\Notification; class VoiceChannel { /** * Send the given notification. * * @param mixed $notifiable * @param \percipioglobal\notifications\models\Notification $notification * @return void */ public function send($notifiable, Notification $notification) { $message = $notification->toVoice($notifiable); // Send notification to the $notifiable... } }
一旦定义了您的通知通道类,您只需将键添加到通知中的via
方法即可。具体值取决于您通道的实现。
<?php namespace App\Notifications; use app\channels\VoiceChannel; use app\channels\messages\VoiceMessage; use percipioglobal\notifications\models\Notification; class InvoicePaid extends Notification { /** * Get the notification channels. * * @param mixed $notifiable * @return array|string */ public function via($notifiable) { return [ 'voice' => '<YOUR_DESTINATION>', ]; } /** * Get the voice representation of the notification. * * @param mixed $notifiable * @return VoiceMessage */ public function toVoice($notifiable) { // ... } }
通道的实现与Laravel的类似,如果您需要特定的通道,有很大可能在Laravel通知通道上找到它,可能只需进行一些实现上的修改。
将添加通道的功能提取到插件中非常容易,如果您实现了自定义插件,请考虑与社区分享。