webzop/yii2-notifications

为Yii2的通知模块

安装次数: 75,950

依赖者: 1

建议者: 0

安全性: 0

星标: 70

关注者: 12

分支: 42

公开问题: 6

类型:yii2-extension

0.3 2020-09-03 15:32 UTC

This package is not auto-updated.

Last update: 2024-09-27 03:52:15 UTC


README

本模块提供了一种通过多种交付渠道发送通知的方法,包括邮件、屏幕、短信(通过Nexmo)等。通知也可以存储在数据库中,以便在您的Web界面上显示。

通知是简短的消息,用于通知用户您的应用程序中发生的事情。例如,如果您正在编写一个计费应用程序,您可能会通过电子邮件和短信渠道向用户发送“发票已支付”通知。

Yii2 Notifications Module

需求

  • PHP 7.1+

    • gmp
    • mbstring
    • curl
    • openssl
  • 推荐使用PHP 7.2+以获得更好的性能。

安装

安装此扩展的首选方法是通过 composer

运行以下命令:

php composer.phar require --prefer-dist webzop/yii2-notifications "*"

或添加以下内容到您的 composer.json 文件的 require 部分:

"webzop/yii2-notifications": "*"

用法

通知通常用作应用程序模块,并像以下示例那样在应用程序配置中配置:

[
    'modules' => [
        'notifications' => [
            'class' => 'webzop\notifications\Module',
            'channels' => [
                'screen' => [
                    'class' => 'webzop\notifications\channels\ScreenChannel',
                ],
                'email' => [
                    'class' => 'webzop\notifications\channels\EmailChannel',
                    'message' => [
                        'from' => 'example@email.com'
                    ],
                ],
                'web' => [
                    'class' => 'webzop\notifications\channels\WebChannel',
                    'enable' => true,                                       // OPTIONAL (default: true) enable/disable web channel
                    'config' => [
                        'serviceWorkerFilepath' => '/service-worker.js',    // OPTIONAL (default: /service-worker.js) is the service worker filename
                        'serviceWorkerScope' => '/app',                     // OPTIONAL (default: './' the service worker path) the scope of the service worker: https://developers.google.com/web/ilt/pwa/introduction-to-service-worker#registration_and_scope
                        'serviceWorkerUrl' => 'url-to-serviceworker',       // OPTIONAL (default: Url::to(['/notifications/web-push-notification/service-worker']))
                        'subscribeUrl' => 'url-to-subscribe-handler',       // OPTIONAL (default: Url::to(['/notifications/web-push-notification/subscribe']))
                        'unsubscribeUrl' => 'url-to-unsubscribe-handler',   // OPTIONAL (default: Url::to(['/notifications/web-push-notification/unsubscribe']))
                        'subscribeLabel' => 'subscribe button label',       // OPTIONAL (default: 'Subscribe')
                        'unsubscribeLabel' => 'subscribe button label',     // OPTIONAL (default: 'Unsubscribe')
                    ],
                    'auth' => [
                        'VAPID' => [
                            'subject' => 'mailto:me@website.com',           // can be a mailto: or your website address
                            'publicKey' => '~88 chars',                     // (recommended) uncompressed public key P-256 encoded in Base64-URL
                            'privateKey' => '~44 chars',                    // (recommended) in fact the secret multiplier of the private key encoded in Base64-URL
                            'pemFile' => 'path/to/pem',                     // if you have a PEM file and can link to it on your filesystem
                            'pem' => 'pemFileContent',                      // if you have a PEM file and want to hardcode its content
                            'reuseVAPIDHeaders' => true                     // OPTIONAL (default: true) you can reuse the same JWT token them for the same flush session to boost performance using
                        ],
                    ],
                ],
            ],
        ],
    ],
];

为了启用Web推送通知,浏览器需要验证您的身份。VAPID标准可以验证所有浏览器的应用程序。您需要为您的服务器创建并提供一个公钥和一个私钥。这些密钥必须安全存储,并且不应更改。

如果您想禁用Web推送通知,只需将标志 'notifications.web.enable' 设置为 false。

要生成未压缩的公钥和私钥(以Base64编码),在您的Linux bash中输入以下内容:

$ openssl ecparam -genkey -name prime256v1 -out private_key.pem
$ openssl ec -in private_key.pem -pubout -outform DER|tail -c 65|base64|tr -d '=' |tr '/+' '_-' >> public_key.txt
$ openssl ec -in private_key.pem -outform DER|tail -c +8|head -c 32|base64|tr -d '=' |tr '/+' '_-' >> private_key.txt

或者您可以使用模块中提供的此方法:

\Minishlink\WebPush\VAPID::createVapidKeys();

创建通知

每个通知都由一个单独的类表示(通常存储在app/notifications目录中)。

namespace app\notifications;

use Yii;
use webzop\notifications\Notification;

class AccountNotification extends Notification
{
    const KEY_NEW_ACCOUNT = 'new_account';

    const KEY_RESET_PASSWORD = 'reset_password';

    /**
     * @var \yii\web\User the user object
     */
    public $user;

    /**
     * @inheritdoc
     */
    public function getTitle(){
        switch($this->key){
            case self::KEY_NEW_ACCOUNT:
                return Yii::t('app', 'New account {user} created', ['user' => '#'.$this->user->id]);
            case self::KEY_RESET_PASSWORD:
                return Yii::t('app', 'Instructions to reset the password');
        }
    }

    /**
     * @inheritdoc
     */
    public function getRoute(){
        return ['/users/edit', 'id' => $this->user->id];
    }
}

发送通知

创建通知后,您可以按照以下方式发送它:

$user = User::findOne(123);

AccountNotification::create(AccountNotification::KEY_RESET_PASSWORD, ['user' => $user])->send();

指定交付渠道

每个通知类都有一个 shouldSend($channel) 方法,它确定通知将通过哪些类型的关键字和渠道进行交付。在这个例子中,通知将通过除了“屏幕”或带有“new_account”关键字之外的所有渠道进行交付。

/**
 * Get the notification's delivery channels.
 * @return boolean
 */
public function shouldSend($channel)
{
    if($channel->id == 'screen'){
        if(!in_array($this->key, [self::KEY_NEW_ACCOUNT])){
            return false;
        }
    }
    return parent::shouldSend($channel);
}

可以通过通知的 renotification_time 属性限制发送给用户的相同关键字/用户的同一通知的数量。只有当在属性指定的期间内没有其他相同用户/关键字的同一通知被发送时,才会发送新的通知。《renotification_time》必须是 DateInterval::__constructor() 接受的字符串。

// For example to limit to 1 notification per hour
$notification = AccountNotification::create(AccountNotification::KEY_RESET_PASSWORD, ['user' => $user]);
$notification->renotification_time = 'PT1H';
$notification->send();

指定特定渠道的发送

每个渠道都有一个接收通知实例并定义该渠道将如何发送通知的方法。但是,您可以通过在通知类中定义 toMail ("to" + [Channel ID]) 来覆盖发送方法。以下示例演示了如何做到这一点:

/**
 * Override send to email channel
 *
 * @param $channel the email channel
 * @return void
 */
public function toEmail($channel){
    switch($this->key){
        case self::KEY_NEW_ACCOUNT:
            $subject = 'Welcome to MySite';
            $template = 'newAccount';
            break;
        case self::KEY_RESET_PASSWORD:
            $subject = 'Password reset for MySite';
            $template = 'resetPassword';
            break;
    }

    $message = $channel->mailer->compose($template, [
        'user' => $this->user,
        'notification' => $this,
    ]);
    Yii::configure($message, $channel->message);

    $message->setTo($this->user->email);
    $message->setSubject($subject);
    $message->send($channel->mailer);
}

自定义渠道

本模块提供了一些预构建的渠道,但您可能想编写自己的渠道来发送通知。为此,您需要定义一个包含发送方法的类。

namespace app\channels;

use webzop\notifications\Channel;
use webzop\notifications\Notification;

class VoiceChannel extends Channel
{
    /**
     * Send the given notification.
     *
     * @param Notification $notification
     * @return void
     */
    public function send(Notification $notification)
    {
        // use $notification->getTitle() ou $notification->getDescription();
        // Send your notification in this channel...
    }

}

您还应在应用程序配置中配置渠道。

[
    'modules' => [
        'notifications' => [
            'class' => 'webzop\notifications\Module',
            'channels' => [
                'voice' => [
                    'class' => 'app\channels\VoiceChannel',
                ],
                //...
            ],
        ],
    ],
]

屏幕渠道

此渠道用于显示如图像预览所示的小型通知。通知将存储在数据库中,因此在使用此渠道之前,您必须运行其迁移脚本。

./yii migrate/up --migrationPath=vendor/webzop/yii2-notifications/migrations/

因此,您可以在应用布局中调用通知小部件来显示生成的通知

<div class="header">
    ...
    <?php echo \webzop\notifications\widgets\Notifications::widget() ?>

</div>

Web 推送通知通道

此通道用于向订阅者发送 Web 推送通知。每个通知订阅都将存储在数据库中,因此在使用此通道之前,您必须运行其迁移脚本

./yii migrate/up --migrationPath=vendor/webzop/yii2-notifications/migrations/

因此,您可以在应用布局中调用通知小部件来显示生成的通知

<div>
    <?php echo \webzop\notifications\widgets\WebNotifications::widget() ?>
</div>

您可以按照以下方式自定义小部件的 HTML 模板。将模板设置为 false 将隐藏所有小部件 HTML,浏览器将提示用户允许通知。如果您自定义 HTML 模板,请记住包含一个 id 为 'js-web-push-subscribe-button' 的按钮

<div>
    <?= \webzop\notifications\widgets\WebNotifications::widget([
        'template' => '... <button id="js-web-push-subscribe-button" disabled="disabled"></button> ...'
    ]) ?>
</div>

请记住,为了在 WebNotifications 小部件初始化时提供服务工作者,将 service-worker.js 文件放置在 Web 根目录下。