snebes / notifications
通知组件
Requires
- php: ^7.1.3
- doctrine/collections: ^1.6
- doctrine/orm: ^2.5
- swiftmailer/swiftmailer: ^6.0
- symfony/event-dispatcher: ^3.4|^4.0
Requires (Dev)
- phpunit/phpunit: ^7.5|^8.0
This package is auto-updated.
Last update: 2024-09-18 15:39:29 UTC
README
snebes/notifications
是一个抽象层,灵感来源于 Laravel,允许您轻松地添加对电子邮件和Web界面消息的支持。
先决条件
此包使用 Symfony 3.4+ 组件以及 SwiftMailer
来提供通知。
安装
将 snebes/notifications
添加到您的 composer.json
文件中
composer require snebes/notifications
如果您想在基于 Symfony 3.4+ 的应用程序中使用此组件,则可以安装 snebes/notifications-bundle
来简化此配置。 查看包文档。
设置/引导
通知组件基于 Symfony 的 Event Dispatcher 构建,这是在 PHP 生态系统中常用的。
use Symfony\Component\EventDispatcher\EventDispatcher; $eventDispatcher = new EventDispatcher(); $notificationSender = new NotificationSender($eventDispatcher);
通知渠道
注册数据库渠道以利用Web界面通知。此组件中包含的数据库渠道依赖于 Doctrine。
$databaseChannel = new DatabaseChannel($doctrineEntityManager); $eventDispatcher->addListener(NotificationEvents::SEND, [$databaseChannel, 'send']);
注册邮件渠道以利用电子邮件通知。此组件中包含的邮件渠道依赖于 SwiftMailer。
$transport = new Swift_SmtpTransport('smtp.example.org', 25); $mailer = new SwiftMailerMailer(new Swift_Mailer($transport)); $mailChannel = new MailChannel($mailer); $eventDispatcher->addListener(NotificationEvents::SEND, [$mailChannel, 'send']);
发送通知
可以通过 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
方法,它确定通知将在哪些渠道上投递。通知可以在 mail
和 database
渠道上发送。
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 数据等信息。
您可以在应用程序的用户界面中查询表以显示通知。但在进行之前,您需要创建一个数据库表来存储您的通知。根据您应用程序的配置,您需要创建具有以下模式的表
CREATE TABLE `sn_notification` ( `id` int(11) NOT NULL AUTO_INCREMENT, `created_at` datetime NOT NULL, `notifiable_id` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL, `notifiable_type` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, `read_at` datetime DEFAULT NULL, `data` json DEFAULT NULL, PRIMARY KEY (`id`), KEY `notifiable_idx` (`notifiable_id`,`notifiable_type`) ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
数据库通知格式化
如果通知支持存储在数据库表中,则类应该实现 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 关系的助手,该关系返回实体的通知。要获取通知,您可以使用 getNotifications()
、getUnreadNotifations()
和 getReadNotifications()
方法。默认情况下,通知将按 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
方法中返回类名。