percipioglobal/craft-notifications

此包已弃用且不再维护。作者建议使用craftpulse/craft-notifications包。

通过多种交付渠道发送通知,包括邮件和Slack。通知也可以存储在数据库中,以便在您的网页界面中显示。

安装: 17,863

依赖项: 0

推荐者: 0

安全: 0

星标: 56

关注者: 6

分支: 6

类型:craft-plugin


README

icon

Craft CMS 3.x 的通知插件

通过多种交付渠道发送通知,包括邮件和Slack。通知也可以存储在数据库中,以便在您的网页界面中显示。

  1. 安装
  2. 简介
  3. 发送通知
  4. 数据库通知
    1. 检索通知
    2. 标记通知为已读
  5. 删除通知
  6. 邮件通知
  7. Slack通知
    1. 格式化Slack通知
    2. 自定义发送者 & 收件人
    3. Slack附件
    4. Markdown附件内容
  8. 通知事件
  9. 自定义渠道

支持开源。买啤酒。

此插件采用MIT许可,这意味着它是一项完全免费的开源软件,您可以随意使用。如果您在使用它并想支持开发,请在Beerpay上为我买一杯啤酒!

要求

此插件需要Craft CMS 3.1.0或更高版本。

安装

要安装插件,请按照以下说明操作。

  1. 打开您的终端并转到您的Craft项目

     cd /path/to/project
    
  2. 然后告诉Composer加载插件

     composer require percipioglobal/craft-notifications
    
  3. 在控制面板中,转到设置 → 插件,并点击“安装”按钮以安装通知。

  4. config.php文件复制到应用程序中的config/notifications.php

  5. 确保通过将以下内容添加到您的composer.json并运行composer dump -o来自动加载通知。

"autoload": {
    "psr-4": {
        "app\\notifications\\": "./notifications"
    }
},

简介

通常,通知应该是简短的信息性消息,通知用户您的应用程序中发生了某事。例如,如果您正在编写账单应用程序,您可能通过电子邮件和短信渠道向用户发送“发票已支付”通知。

创建通知

每个通知都由单个类表示(存储在您的应用程序的notifications目录中)。您必须手动创建它,或者当您运行notifications/make命令时,它将为您创建。

./craft notifications/make BlogPostAdded

此命令将在您的notifications目录中放置一个新的通知类。每个通知类都包含一个via方法和多个消息构建方法(例如toMailtoDatabase),这些方法将通知转换为针对特定渠道优化的消息。

发送通知

通知可以通过两种方式发送,一种是从配置文件在事件触发时发送,另一种是从您自己的插件发送。

首先,让我们看看如何在添加新博客文章时配置发送通知。

<?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,它包含 senderisNew 属性,利用这些信息我们可以确定只有在条目来自 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 类应定义一个 toDatabasetoArray 函数。

这可以很简单,例如

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!');
}

自定义发送者和接收者

您可以使用 fromto 方法来自定义发送者和接收者。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.');
        });
}

上面的示例将生成一个如下所示的 Slack 消息:Basic Slack attachment

附件还允许您指定一个应向用户展示的数据数组。给定的数据将以表格格式展示,便于阅读。

/**
 * 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消息:基本的Slack附件

Markdown附件内容

如果您的某些附件字段包含Markdown,您可以使用markdown方法指示Slack解析并显示给定的附件字段作为Markdown格式的文本。此方法接受的值有:pretexttext和/或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_SENDNotificationsService::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通知通道上找到它,可能只需进行一些实现上的修改。

将添加通道的功能提取到插件中非常容易,如果您实现了自定义插件,请考虑与社区分享。

Percipio Global Ltd.提供。