snebes/notifications-bundle

为 Symfony 项目提供的 snebes/notifications-bundle 集成

资助包维护!
www.paypal.me/snebes

安装: 17

依赖: 0

建议者: 0

安全: 0

星标: 4

关注者: 2

分支: 0

开放问题: 0

类型:symfony-bundle

v1.0.0 2019-09-18 04:59 UTC

This package is auto-updated.

Last update: 2024-09-22 18:07:17 UTC


README

GitHub release GitHub license Scrutinizer build Scrutinizer coverage Scrutinizer code quality PHP

snebes/notifications-bundle 为您的 Symfony 项目提供了 snebes/notifications 的集成。Notifications 是一个抽象层,受到 Laravel 的启发,它允许您轻松添加对电子邮件和网页界面消息的支持。

此捆绑包预安装的示例 Symfony 应用程序可用。请查看 snebes/notifications-demo

先决条件

此捆绑包需要 Symfony 3.4+,并使用 doctrine/doctrine-bundlesymfony/swiftmailer-bundle 来提供通知。

安装

snebes/notifications-bundle 添加到您的 composer.json 文件

composer require snebes/notifications-bundle
注册捆绑包
Symfony 3

app/AppKernel.php 中注册捆绑包

public function registerBundles()
{
    return array(
        // ...
        new SN\Bundle\NotificationsBundle\SNNotificationsBundle(),
    );
}
Symfony 4

config/bundles.php 中注册捆绑包。Flex 将为您完成此操作。

return [
    // ...
    SN\Bundle\NotificationsBundle\SNNotificationsBundle::class => ['all' => true],
];

创建通知

每个通知由一个类(通常存储在 src/Notifications 目录中)表示。如果您在应用程序中看不到此目录,当您运行 make:sn:notification 命令时,它将为您创建。

bin/console make:sn:notification

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

发送通知

可以通过 NotificationSender 服务发送通知。

<?php

namespace App\Service;

use App\Entity\User;
use App\Notifications\OrderNotification;
use SN\Notifications\NotificationSender;

class UserService
{
    private $notificationSender;

    public function __construct(NotificationSender $notificationSender)
    {
        $this->notificationSender = $notificationSender;    
    }

    public function send(User $user)
    {
        $this->notificationSender->send($user, new OrderNotification());
    }
}

此组件提供了辅助函数,使类,如上面的 User 类,可以接受通知。《NotifiableTrait》为任何类添加了接收数据库或邮件消息的能力。

要从实体引用数据库通知,需要为 Doctrine 配置一个 $notification 字段以映射关系。

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use SN\Bundle\NotificationsBundle\Entity\Notification;
use SN\Notifications\Contracts\NotifiableInterface;
use SN\Notifications\NotifiableTrait;

/**
 * @ORM\Entity()
 */
class User implements NotifiableInterface
{
    use NotifiableTrait;

    /**
     * This field is used by the Mail channel.
     * 
     * @var string
     */
    private $email = 'demo@example.com';

    /**
     * This field is used by the SMS channel.
     * 
     * @var string
     */
    private $phoneNumber = '+1 555 555 5555';

    /**
     * @var Notification[]
     *
     * @ORM\ManyToMany(targetEntity=Notification::class)
     * @ORM\JoinTable(name="user_notifications")
    */
    private $notifications;
}

指定交付渠道

每个通知类都有一个 via 方法,用于确定通知将在哪些渠道上交付。通知可以在 maildatabase 渠道上发送。

via 方法接收一个 NotifiableInterface 实例,这将是一个即将发送通知的类的实例。您可以使用 NotifiableInterface 来确定通知应该在哪些渠道上交付。

/**
 * Get the notification's delivery channels.
 *
 * @param NotifiableInterface $notifiable
 *
 * @return array
 */
public function via(NotifiableInterface $notifiable): array
{
    return $notifiable->doNotSendEmail() ? ['database'] : ['database', 'mail'];
}

邮件通知

如果通知支持作为电子邮件发送,则该类应实现 MailableInterface 并定义一个 toMail 方法。此方法将接收一个 NotifiableInterface 实体,并应返回一个 SN\Notifications\Contracts\EmailInterface; 实例。让我们看看一个 toMail 方法的示例。

<?php

namespace App\Notification;

use SN\Notifications\Contracts\EmailInterface;
use SN\Notifications\Contracts\MailableInterface;
use SN\Notifications\Contracts\NotifiableInterface;
use SN\Notifications\Contracts\NotificationInterface;
use SN\Notifications\Email\Address;
use SN\Notifications\Email\Email;

class OrderNotification implements NotificationInterface, MailableInterface
{
    /**
     * Get the notification's delivery channels.
     *
     * @param NotifiableInterface $notifiable
     *
     * @return array
     */
    public function via(NotifiableInterface $notifiable): array
    {
        return ['mail'];
    }

    /**
     * Get the mail representation of the notification.
     *
     * @param NotifiableInterface $notifiable
     *
     * @return EmailInterface
     */
    public function toMail(NotifiableInterface $notifiable): EmailInterface
    {
        return (new Email())
            ->from(new Address('orders@example.com'))
            ->subject('Thank you for your order.')
            ->text('We are processing your order right now!');
    }
}

在此示例中,我们创建了一个具有主题和文本行的电子邮件。由 Email 对象提供的这些方法使格式化小型交易性电子邮件变得简单快捷。邮件通道将自动为每个 NotifiableInterface 填充 to 地址。

自定义收件人

当通过 mail 通道发送通知时,通知系统将自动在您的 NotifiableInterface 实体上查找 email 属性。您可以通过在实体上定义一个 routeNotificationForMail 方法来自定义用于发送通知的电子邮件地址。

<?php

namespace App\Entity;

use SN\Notifications\Contracts\NotifiableInterface;
use SN\Notifications\Contracts\NotificationInterface;use SN\Notifications\NotifiableTrait;

class User implements NotifiableInterface
{
    use NotifiableTrait;

    /**
     * Route notifications for the mail channel.
     *
     * @param NotificationInterface $notification
     *
     * @return string
     */
    public function routeNotificationForMail(NotificationInterface $notification)
    {
        return $this->getEmailAddress();
    }
}

数据库通知

先决条件

数据库通知通道将通知信息存储在数据库表中。这个表将包含通知类型以及描述通知的自定义JSON数据。

您可以通过查询表来在应用程序的用户界面中显示通知。但在您这样做之前,您需要创建一个数据库表来存储您的通知。您可以使用doctrine:migration:diff命令生成一个具有适当表模式的迁移。

bin/console doctrine:migration:diff
bin/console doctrine:migration:migrate

数据库通知格式化

如果通知支持存储在数据库表中,则类应该实现ArrayableInterface并定义一个toArray方法。此方法将接收一个NotifiableInterface实体,并应该返回一个纯PHP数组。返回的数组将被编码为JSON并存储在通知表的data列中。让我们看看一个toArray方法的例子。

<?php

namespace App\Notification;

use SN\Notifications\Contracts\ArrayableInterface;
use SN\Notifications\Contracts\NotifiableInterface;
use SN\Notifications\Contracts\NotificationInterface;

class OrderNotification implements NotificationInterface, ArrayableInterface
{
    /**
     * Get the notification's delivery channels.
     *
     * @param NotifiableInterface $notifiable
     *
     * @return array
     */
    public function via(NotifiableInterface $notifiable): array
    {
        return ['mail'];
    }

    /**
     * Get the mail representation of the notification.
     *
     * @param NotifiableInterface $notifiable
     *
     * @return array
     */
    public function toArray(NotifiableInterface $notifiable): array
    {
        return [
            'order_id' => $this->orderId,
            'amount'   => $this->amount,
        ];
    }
}

访问通知

一旦通知存储在数据库中,您需要一种方便的方式来从您的可通知实体中访问它们。包含在此组件中的NotifiableTrait包含对$notifications关系的辅助器,该关系返回实体的通知。要获取通知,您可以使用getNotificationsgetUnreadNotificationsgetReadNotifications方法。默认情况下,通知将按createdAt时间戳排序。

$user = $this->getUser();

foreach ($user->getUnreadNotifications() as $notification) {
    echo $notification->data['message'];
}

标记通知为已读

通常,当用户查看通知时,您会想将其标记为“已读”。SSN\Bundle\NotificationsBundle\Entity\Notification实体类提供了一个setReadAt方法,该方法更新通知数据库记录上的readAt列。

$user = $this->getUser();

foreach ($user->getUnreadNotifications() as $notification) {
    $notification->setReadAt(new \DateTime());
}

通知事件

当发送通知时,组件会分发多个事件,您可以使用这些事件来修改通知的处理方式。

NotificationEvents::SENDING

事件类:SN\Notifications\Event\NotificationSendingEvent

在发送通知之前会分发此事件。它用于向通知添加更多信息或阻止通知发送。

执行此命令以找出已注册的此事件的监听器和它们的优先级。

bin/console debug:event-dispatcher sn.notifications.sending

NotificationEvents::SEND

事件类:SN\Notifications\Event\NotificationSendEvent

在发送通知时,会分发此事件。其主要用途是将通知发送到所需的通道,这是此组件内部使用通道的方式。

执行此命令以找出已注册的此事件的监听器和它们的优先级。

bin/console debug:event-dispatcher sn.notifications.send

NotificationEvents::SENT

事件类:SN\Notifications\Event\NotificationSentEvent

在通知成功发送后,会分发此事件。它用于在发送的通知上执行任务。

执行此命令以找出已注册的此事件的监听器和它们的优先级。

bin/console debug:event-dispatcher sn.notifications.sent

NotificationEvents::EXCEPTION

事件类:SN\Notifications\Event\NotificationExceptionEvent

在处理通知时出现错误时,会立即分发此事件。它用于从错误中恢复或修改通知。

执行此命令以找出已注册的此事件的监听器和它们的优先级。

bin/console debug:event-dispatcher sn.notifications.exception

自定义通道

此组件附带了一些通知通道,但您可能想编写自己的通道来通过其他方法发送通知。分发的通知事件使其变得简单。要开始,定义一个类,该类侦听或订阅NotificationEvents::SEND事件。

<?php

namespace App\Channel;

use SN\Notifications\Event\NotificationSendEvent;
use SN\Notifications\NotificationEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class CustomChannel implements EventSubscriberInterface
{
    /**
     * @return array
     */
    public static function getSubscribedEvents(): array
    {
        return [
            NotificationEvents::SEND => 'send',
        ];
    }

    /**
     * Send the given notification.
     *
     * @param NotificationSendEvent $event
     */
    public function send(NotificationSendEvent $event): void
    {
        $notifiable = $event->getNotifiable();
        $notification = $event->getNotification();

        // Send notification to the $notifiable.
    }
}

一旦定义了您的通知通道类,您就可以从任何通知的via方法返回该类名。