craftpulse / craft-notifications
通过多种传输渠道发送通知,包括邮件和Slack。通知也可以存储在数据库中,以便在您的Web界面中显示。
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-09-12 14:12:54 UTC
README
Craft CMS 3.x 的通知插件
通过多种传输渠道发送通知,包括邮件和Slack。通知也可以存储在数据库中,以便在您的Web界面中显示。
支持开源。买啤酒。
此插件采用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
),这些方法将通知转换为针对特定渠道优化的消息。
发送通知
通知可以通过两种方式发送,一种是在配置文件中当 event
触发时,另一种是从您的插件中。
首先,让我们看看如何配置在例如添加新博客文章时发送通知
<?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个月
。如果您想自定义时间框架,请提供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
方法接受一个用户名和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'); }
您也可以使用图像作为您的标志而不是emoji。
/** * 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 Notification Channels 找到它,只需要少量实现更改。
添加通道的功能很容易提取到插件中,如果您实现了自定义插件,请考虑与社区分享。
由 Percipio Global Ltd. 提供