damianociarla / notification-bundle
DCSNotificationBundle 是一个 Symfony2 扩展包,允许您向任何接收者发送任何类型的通知
Requires
- php: >=5.3
- symfony/symfony: ~2.3
This package is not auto-updated.
Last update: 2024-09-14 16:07:05 UTC
README
DCSNotificationBundle 是一个允许您发送通知的 Symfony2 扩展包。
使用示例
为了说明此扩展包的工作原理,我们将通过一个示例进行说明。我们有一个博客应用程序,允许已登录用户对已发布的帖子添加评论。
当读者在帖子下留言时,帖子的作者和所有之前的评论者都会收到关于新评论的电子邮件。作为负责任的开发者,我们给所有评论者提供了禁用通知的选项。
流程
DCSNotificationBundle 提供了三个重要的服务
dcs_notification.service.notification
通过notify()
方法处理通知dcs_notification.manager.component
负责创建通知的主题
dcs_notification.service.notifier
通过process()
方法处理通知
对于每种类型的通知,我们负责创建一个 通知器 和一个 传输器,它们知道如何处理通知。
配置
要使用 DSCNotificationBunde,我们需要配置该扩展包和我们的通知器。
以下是一个扩展包配置示例
dcs_notification:
db_driver: orm
class:
model:
component: Blog\NotificationBundle\Entity\Component
component_setting: Blog\NotificationBundle\Entity\ComponentSetting
notification: Blog\NotificationBundle\Entity\Notification
notification_component: Blog\NotificationBundle\Entity\NotificationComponent
recipient: Blog\NotificationBundle\Entity\Recipient
transporters:
mail:
id: blog_notification.transporter.mail
actions:
new_comment:
transporters:
mail:
id: mail
config:
template: BlogNotificationBundle:Email:new_comment.html.twig
dcs_notification
是 DCSNotificationBundle 配置的键。要使用扩展包,John 首先配置了必需的键
db_driver
设置为orm
告诉 Symfony 2 使用 Doctrine ORMclass
包含模型类列表。如果我们不需要复杂的类,我们可以直接扩展扩展包提供的基类Blog\NotificationBundle\Entity\Component extends DCS\NotificationBundle\Entity\Component
Blog\NotificationBundle\Entity\ComponentSetting extends DCS\NotificationBundle\Entity\ComponentSetting
Blog\NotificationBundle\Entity\Notification extends DCS\NotificationBundle\Entity\Notification
Blog\NotificationBundle\Entity\NotificationComponent extends DCS\NotificationBundle\Entity\NotificationComponent
Blog\NotificationBundle\Entity\Recipient extends DCS\NotificationBundle\Entity\Recipient
transporters
定义与有效服务关联的传输器列表actions
是与传输器相关联的可访问操作列表
为了能够使用扩展包,我们需要配置通知器。以下是一个配置示例
services:
blog.notification_bundle.notifier.new_comment:
class: Blog\NotificationBundle\Notifier\NewCommentNotifier
tags:
- { name: dcs_notification.notifier }
这样我们就添加了 blog.notification_bundle.notifier.new_comment
通知器。
通知通知
dcs_notification.service.notification
服务代表通知流程的入口点。该服务通过以下方式使用 notify()
方法
$commentComponent = $this->componentManager->findOrCreateComponent($comment, $comment->getId()); $this->notificationService->notify($commentComponent, 'new_comment', array('url' => $currentUrl));
《notify()` 方法的第一个参数称为 subject
。这可以是任何东西,只要它被包裹在 DCS\NotificationBundle\Model\ComponentManagerInterface
类型对象中。在示例中,我们决定将评论传递给 notify()
方法,因为评论中包含了大量关于正在发生的事情的信息:评论本身、评论作者、评论的帖子以及从帖子中获取的作者、帖子上的其他评论以及最后所有其他评论的作者。第二个参数是 new_comment
,称为通知的 action
。我们稍后会回到 action
。第三个参数是可选的,包含我们想要以后能够访问的附加数据。
《notify()` 方法实际上并不处理通知,而是将其保存为“挂起”状态。
另一种传递数据给 notify()
方式
我们本可以决定以不同的方式实现通知,将评论作为第三个参数传递,并使主题更通用
$commentComponent = $this->componentManager->findOrCreateComponent('the_comment_subject', $comment->getId()); $this->notificationService->notify( $commentComponent, 'new_comment', array( 'url' => $currentUrl, 'id' => $comment->getId() ) );
此更改将影响我们处理通知的方式。
处理挂起通知
《dcs_notification.manager.notification》服务公开了《findAllNotificationToSend()`》方法,它返回所有挂起通知。
有了挂起通知的列表,可以使用《dcs_notification.service.notifier》服务进行处理,如下所示
$notificationsToSend = $this->getContainer()->get('dcs_notification.manager.notification')->findAllNotificationToSend($limit); $notifierService = $this->getContainer()->get('dcs_notification.service.notifier'); foreach ($notificationsToSend as $notification) { $notifierService->process($notification); }
上述代码可以用于命令行命令集,通过 cron 定期运行。
通知器
到目前为止,我们有一个挂起通知的列表正在逐个处理。当调用 process()
方法时,发生两件重要的事情
- 每个通知器都被询问是否知道如何管理当前通知,如果结果是肯定的,则将通知传递给它
- 调用传输器
通知器是实现《DCS\NotificationBundle\Notifier\NotifierInterface》接口的类。
在我们的示例中,我们有一个新的通知,具有《new_comment》操作,并且可以使用有效的通知器来管理通知的接收者
<?php namespace Blog\NotificationBundle\Notifier; use DCS\NotificationBundle\Model\NotificationComponentInterface; use DCS\NotificationBundle\Model\NotificationInterface; use DCS\NotificationBundle\Model\NotificationManagerInterface; use DCS\NotificationBundle\Notifier\Collection\RecipientCollectionInterface; use DCS\NotificationBundle\Notifier\NotifierInterface; use Blog\PostBundle\Entity\Post; use Blog\PostBundle\Entity\Comment; use Blog\PostBundle\Repository\CommentRepository; use Blog\UserBundle\Entity\User; class NewCommentNotifier implements NotifierInterface { protected $notificationManager; protected $projectRepository; function __construct(NotificationManagerInterface $notificationManager, CommentRepository $commentRepository) { $this->notificationManager = $notificationManager; $this->commentRepository = $commentRepository; } public function supports(NotificationInterface $notification) { return $notification->getAction() == 'new_comment'; } public function notify(NotificationInterface $notification, RecipientCollectionInterface $recipients) { $notificationComponents = $this->notificationManager->findAllNotificationComponent($notification); /** @var NotificationComponentInterface $notificationComponent */ foreach ($notificationComponents as $notificationComponent) { if ($notificationComponent->getType() == 'comment') { /** @var Comment $comment */ $comment = $notificationComponent->getComponent()->getData(); if ($comment instanceof Comment) { $commentAuthor = $comment->getAuthor(); $post = $comment->getPost(); $postAuthor = $post->getAuthor(); if ($comment->getAuthor()->getId() != $postAuthor->getId()) { $recipients->add('Blog\UserBundle\Entity\User', $postAuthor->getId()); } $commenters = $this->commentRepository->findAllCommentersToPost($post); /** @var User $member */ foreach ($commenters as $commenter) { if ($commenter->getId() != $postAuthor->getId() && $commenter->getId() != $postAuthor->getId()) { $recipients->add('Blog\UserBundle\Entity\User', $commenter->getId()); } } } } } } }
使用《Blog\NotificationBundle\Notifier\CommentNotifier》类,我们现在能够将正确的接收者添加到通知中:帖子的作者和所有评论者。通知准备好发送到传输器。
传输器
传输器是实现《DCS\NotificationBundle\Transporter\TransporterInterface》接口的类。接口要求开发人员实现两个方法:`setConfiguration()` 和 `send()`
<?php namespace DCS\NotificationBundle\Transporter; use DCS\NotificationBundle\Model\NotificationInterface; use DCS\NotificationBundle\Model\RecipientInterface; interface TransporterInterface { public function setConfiguration($config); public function send(NotificationInterface $notification, array $additionalData, RecipientInterface $recipient); }
如果我们回顾《actions.new_comment.transporters.mail.config》配置,我们定义了一个选项,它指定与传输器关联的模板。这些选项通过 `setConfiguration()` 方法注入到 `blog_notification.transporter.mail` 服务中。
`send()` 方法负责执行发送通知的实际工作。它将接受一个 $notification
对象、一个 $components
数组和 一个 $recipient
对象。
$notification
对象包含需要发送的通知主题$additionalData
包含传递给《$notificationService->notify()`》方法的第三个参数的数据$recipient
是接收者
`send()` 方法的示例实现可能如下所示
public function send(NotificationInterface $notification, array $additionalData, RecipientInterface $recipient) { if (!isset($this->config['template'])) { throw new \Exception('Template must be set in this transporter'); } $recipient = $recipient->getComponent()->getData(); $templateName = $this->config['template']; $attach = array(); $context = array( 'siteUrlHttp' => $this->siteUrlHttp, 'subject' => $notification->getSubject()->getData(), 'notification' => $notification, 'recipient' => $recipient, ); $email = null; if ($recipient instanceof User) { $email = $recipient->getEmailCanonical(); } elseif (is_array($recipient) && isset($recipient['email']) && is_scalar($recipient['email'])) { $email = $recipient['email']; } if (!empty($email)) { $this->sendMessage($templateName, $context, $email, $attach); } } private function sendMessage($templateName, $context, $toEmail, array $attach = null) { // send the email }