rias / 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:07:48 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, ], ], ];
这里我们监听 EVENT_AFTER_SAVE
事件,在Craft的 Entry
类上,这将导致我们每次保存条目时触发通知。
在我们的 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 Notification Channels 找到它,只需进行一些实现上的修改。
将添加通道的功能提取为插件是非常容易的,如果你实现了自定义插件,请考虑与社区分享。
由 Percipio Global Ltd. 提供