以各种方式通知
以各种方式通知
留言簿应用程序收集关于会议的反馈。但我们并不擅长给用户反馈。
由于评论是经过审核的,他们可能不明白为什么他们的评论没有立即发布。他们甚至可能认为是技术问题而重新提交。在发表评论后给他们反馈就太好了。
此外,我们应该在他们的评论发布后ping他们。我们要他们的电子邮件,所以我们最好使用它。
通知用户的方法有很多种。电子邮件可能是你首先想到的媒介,但web应用程序中的通知是另一个。我们甚至可以考虑发送短信,在Slack或Telegram上发布消息。有很多选择。
Symfob娱乐下载ony Notifier组件实现了许多通知策略。
在浏览器中发送Web应用程序通知
作为第一步,让我们通知用户,在他们提交评论后,评论将直接在浏览器中进行审核:
12 34 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
——/ src /控制器/ ConferenceController.php+ + + b / src /控制器/ ConferenceController.php使用Symfony\Component\Htob娱乐下载tpFoundation\File\Exception\FileException;使用Syob娱乐下载mfony \ HttpFoundation \ \组件请求;组件使用ob娱乐下载Symfony \ \ HttpFoundation \反应;使用Syob娱乐下载mfony \组件\ \ MessageBusInterface使者;+使用Syob娱乐下载mfony \组件\ \通知\通知通知;+使用Syob娱乐下载mfony \ \通知\ NotifierInterface组件;使用Syob娱乐下载mfony \组件\路由\注释\路线;类ConferenceController扩展了AbstractController的Request $ Request,会议$会议$ CommentRepository,+ NotifierInterface#[autoire ('%photo_dir%')] string $photoDir,): Response {$comment = new comment ();@@ -74,9 +77,15 @@类ConferenceController扩展AbstractController];$this->总线->调度(新的评论消息($comment->getId(), $context));+ $notifier->send(新的通知('感谢您的反馈;您的评论将在审核后发布。”,(“浏览器”)));+return $this->redirectToRoute('conference', ['slug' => $conference->getSlug()]);}+ if ($form->isSubmitted()) {+ $notifier->send(new Notification('Can you check your submission?它有一些问题。”,(“浏览器”)));+}+$offset = max(0, $request->query->getInt('offset', 0));$paginator = $commentRepository->getCommentPaginator($conference, $offset);
的通知发送一个通知来收件人通过一个通道.
通知有一个主题、一个可选内容和一个重要性。
通知根据其重要性在一个或多个通道上发送。例如,你可以通过短信发送紧急通知,也可以通过电子邮件发送常规通知。
对于浏览器通知,我们没有收件人。
浏览器通知使用flash的消息通过通知部分。我们需要通过更新会议模板来显示它们:
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16
——/模板/会议/ show.html.twig+ + + b /模板/会议/ show.html.twig@@ -3,6 +3,13 @@{% block title %}会议留言簿- {{Conference}}{% endblock %} {% block正文%}+{%消息在app.flash ('notification') %}+ + {{message}}+ + < / div >+ {% endfor %}+ {{conference}}会议
用户现在将被通知他们的提交已被审核:
作为额外的奖励,如果有表单错误,我们在网站顶部有一个漂亮的通知:
提示
Flash消息使用HTTP会话系统作为存储介质。主要的后果是禁用HTTP缓存,因为必须启动会话系统来检查消息。
方法中添加flash消息片段的原因show.html.twig
而不是在基础模板中,因为我们会失去主页的HTTP缓存。
通过电子邮件通知管理员
而不是发送电子邮件MailerInterface
要通知管理员一条评论已经发布,切换到使用消息处理程序中的Notifier组件:
12 34 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
——MessageHandler / src / / CommentMessageHandler.php+ + + MessageHandler b / src / / CommentMessageHandler.php@@命名空间App\MessageHandler;使用App \ ImageOptimizer;使用App \ \ CommentMessage消息;+使用App \ \ CommentReviewNotification通知;使用App \ Repository \ CommentRepository;使用App \ SpamChecker;使用原则\ ORM \ EntityManagerInterface;使用日志Psr \ \ LoggerInterface;桥用Symob娱乐下载fony \ \树枝\ Mime \ NotificationEmail;使用Syob娱乐下载mfony \ DependencyInjection \属性\ \组件自动装配;用Symfob娱乐下载ony \ \梅勒\ MailerInterface组件;使用Syob娱乐下载mfony \信使\ \组件属性\ AsMessageHandler;使用Syob娱乐下载mfony \组件\ \ MessageBusInterface使者;+使用Syob娱乐下载mfony \ \通知\ NotifierInterface组件;使用Syob娱乐下载mfony \工作流组件\ \ WorkflowInterface;#[AsMessageHandler] @@ -24,8 +24,7 @@ class CommentMessageHandler private CommentRepository $ CommentRepository, private MessageBusInterface $bus, private WorkflowInterface $commentStateMachine,- private MailerInterface $mailer- #[自动连接('%admin_email%')] private string $adminEmail,+ private NotifierInterfaceLoggerInterface $logger = null, @@ -50,13 +49,7 @@类CommentMessageHandler $this->entityManager->flush();$ this - >总线- >调度($消息);} elseif ($this->commentStateMachine->can($comment, 'publish') || $this->commentStateMachine->can($comment, 'publish_ham')) {- $this->mailer->send((new NotificationEmail())- ->subject('新评论已发布')——> htmlTemplate(邮件/ comment_notification.html.twig)- - > ($ this - > adminEmail)- - > ($ this - > adminEmail)- ->context(['comment' => $comment])-);+ $this->notifier->send(new CommentReviewNotification($comment),…$this->notifier-> getadminreceivers ());} elseif ($this->commentStateMachine->can($comment, 'optimize')) {if ($comment->getPhotoFilename()) {$this->imageOptimizer->resize($this->photoDir.'/'.$comment->getPhotoFilename());
的getAdminRecipients ()
方法返回在通知器配置中配置的admin收件人;现在更新它,添加您自己的电子邮件地址:
1 2 3 4 5 6 7 8
——/ config /包/ notifier.yaml+ + + b / config /包/ notifier.yaml@@ -13,4 +13,4 @@ framework: medium: ['email'] low: ['email'] admin_attachments:- - {email: admin@example.com}+ - {email: "%env(string:default:default_admin_email:ADMIN_EMAIL)%"}
现在,创建CommentReviewNotification
类:
的asEmailMessage ()
方法从EmailNotificationInterface
是可选的,但它允许自定义电子邮件。
使用Notifier而不是直接使用mailer来发送电子邮件的一个好处是,它将通知从用于它的“通道”中分离出来。如您所见,没有明确说明通知应该通过电子邮件发送。
相反,通道是在配置/包/ notifier.yaml
取决于重要性有关通知书(低
默认情况下):
我们已经讨论过浏览器
和电子邮件
频道。让我们看看更花哨的。
与管理员聊天
老实说,我们都在等待积极的反馈。或者至少是建设性的反馈。如果有人发表评论,用“很棒”或“很棒”这样的词,我们可能会比其他人更快地接受他们。
对于这类消息,除了常规的电子邮件外,我们还希望通过Slack或Telegram等即时通讯系统收到提醒。
为Symfony Notifier安装Slack支持ob娱乐下载:
1
$ob娱乐下载Symfony作曲家要求懈怠通知
首先,将Slack DSN与Slack访问令牌和想要发送消息的Slack通道标识符组合在一起:松:/ / ACCESS_TOKEN@default ?通道=通道
.
由于访问令牌是敏感的,将Slack DSN存储在秘密存储中:
1
$ob娱乐下载Symfony控制台的秘密:集SLACK_DSN
对生产进行同样的操作:
1
$ob娱乐下载Symfony控制台的秘密:集SLACK_DSN - env =刺激
启用chatter Slack支持:
12 3 4 5 6 7 8 9 10 11 12
——/ config /包/ notifier.yaml+ + + b / config /包/ notifier.yaml@@ -1,7 +1,7 @@框架:通知:- # chatter_transports:- # slack: '%env(SLACK_DSN)%'+ chatter_transports:+ slack: '%env(SLACK_DSN)%'# texter_transsports: # twilio: '%env(TWILIO_DSN)%'
更新Notification类以根据注释文本内容路由消息(一个简单的正则表达式就可以完成这项工作):
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
——/ src / / CommentReviewNotification.php通知+ + + b / src / / CommentReviewNotification.php通知@@ Symfony\Componentob娱乐下载\Notifier\Message\EmailMessage;组件使用ob娱乐下载Symfony \ \通知\ \ EmailNotificationInterface通知;使用Syob娱乐下载mfony \组件\ \通知\通知通知;使用Syob娱乐下载mfony \组件\通知\接受者\ EmailRecipientInterface;+使用Syob娱乐下载mfony \组件\通知\接受者\ RecipientInterface;class CommentReviewNotification extends Notification实现EmailNotificationInterface {@@ -26,4 +27,15 @@ class CommentReviewNotification实现EmailNotificatio return $message;}++公共函数getChannels(RecipientInterface $ receiver):数组+ {+如果(preg_match (' {\ b(好棒|)\ b}我,$ this - >评论> getText ())) {+ return ['email', 'chat/slack'];+}++ $ this - >重要性(通知::IMPORTANCE_LOW);++ return ['email'];+}}
我们也改变了“常规”评论的重要性,因为它稍微调整了电子邮件的设计。
并完成了!在文本中提交一个“awesome”的评论,你应该会在Slack上收到一条消息。
至于电子邮件,您可以实现ChatNotificationInterface
来覆盖Slack消息的默认呈现:
12 34 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
——/ src / / CommentReviewNotification.php通知+ + + b / src / / CommentReviewNotification.php通知@@ -3,13 +3,18 @@名称空间的应用程序\通知;使用App \实体\评论;+使用Syob娱乐下载mfony \桥组件\通知\ \松弛\ \ SlackDividerBlock块;+使用Syob娱乐下载mfony \桥组件\通知\ \松弛\ \ SlackSectionBlock块;+使用Syob娱乐下载mfony \桥组件\通知\ \松弛\ SlackOptions;+使用Syob娱乐下载mfony \组件\ \ ChatMessage通知\消息;使用Syob娱乐下载mfony \组件\ \ EmailMessage通知\消息;+使用Syob娱乐下载mfony \组件\通知\ \ ChatNotificationInterface通知;组件使用ob娱乐下载Symfony \ \通知\ \ EmailNotificationInterface通知;使用Syob娱乐下载mfony \组件\ \通知\通知通知;使用Syob娱乐下载mfony \组件\通知\接受者\ EmailRecipientInterface;使用Syob娱乐下载mfony \组件\通知\接受者\ RecipientInterface;-class CommentReviewNotification扩展Notification实现EmailNotificationInterface+类CommentReviewNotification扩展Notification实现EmailNotificationInterface, ChatNotificationInterface{公共函数__construct(private Comment $ Comment, @@ -28,6 +33,28 @@类CommentReviewNotification扩展Notification实现EmailNotificatio返回$message;}+公共函数asChatMessage(RecipientInterface $ receiver, string $transport = null):+ {+ if ('slack' !== $transport) {+返回null;+}++ $message = ChatMessage::fromNotification($this, $ receiver, $transport);+ $消息- >主题($ this - > getSubject ());+ $message->选项((新的SlackOptions())+ - > iconEmoji(“大作”)+ - > iconUrl(“https://guestbook.example.com”)+ - - - >用户名(“留言板”)+ ->block((new SlackSectionBlock())->text($this->getSubject())))+ ->block(new SlackDividerBlock())+ ->block((new SlackSectionBlock())+ - >文本(sprintf (' % s (% s)说:% s的,$ this - >评论> getAuthor (), $ this - >评论> getEmail (), $ this - >评论> getText ()))+)+);++返回$message;+}+公共函数getChannels(RecipientInterface $ receiver):数组{if (preg_match('{\b(great|awesome)\b}i', $this->comment->getText())) {
这样更好,但让我们更进一步。如果能够直接接受或拒绝来自Slack的评论,这不是很棒吗?
更改通知以接受评审URL,并在Slack消息中添加两个按钮:
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
——/ src / / CommentReviewNotification.php通知+ + + b / src / / CommentReviewNotification.php通知@@ -3,6 +3,7 @@名称空间的应用程序\通知;使用App \实体\评论;+使用Syob娱乐下载mfony \桥组件\通知\ \松弛\ \ SlackActionsBlock块;桥组件使ob娱乐下载用Symfony \ \通知\ \松弛\ \ SlackDividerBlock块;桥组件使ob娱乐下载用Symfony \ \通知\ \松弛\ \ SlackSectionBlock块;使用Syob娱乐下载mfony \桥组件\通知\ \松弛\ SlackOptions;@@ -18,6 +19,7 @@类CommentReviewNotification扩展Notification实现EmailNotificatio{公共函数__construct(private Comment $ Comment,+私有字符串$reviewUrl,) {parent::__construct('新评论发布');} @@ -50,6 +52,10 @@类CommentReviewNotification扩展Notification实现EmailNotificatio ->block((新的SlackSectionBlock()) ->text(sprintf('%s (%s)说:%s', $this->comment->getAuthor(), $this->comment->getEmail(), $this->comment->getText()))) . .+ ->block((new SlackActionsBlock())+ ->按钮('接受',$this->reviewUrl, 'primary')+ ->按钮('拒绝',$this->reviewUrl.'?拒绝= 1”、“危险”)+));返回美元消息;
现在的问题是追溯变化。首先,更新消息处理程序以传递评审URL:
12 3 4 5 6 7 8 9 10 11 12
——MessageHandler / src / / CommentMessageHandler.php+ + + MessageHandler b / src / / CommentMessageHandler.php@@ -49,7 +49,8 @@类CommentMessageHandler $this->entityManager->flush();$ this - >总线- >调度($消息);} elseif ($this->commentStateMachine->can($comment, 'publish') || $this->commentStateMachine->can($comment, 'publish_ham')) {- $this->notifier->send(new CommentReviewNotification($comment),…+ $notification = new CommentReviewNotification($comment, $message->getReviewUrl());+ $this->notifier->send($notification,…$this->notifier-> getadmin收件人());} elseif ($this->commentStateMachine->can($comment, 'optimize')) {if ($comment->getPhotoFilename()) {$this->imageOptimizer->resize($this->photoDir.'/'.$comment->getPhotoFilename());
正如你所看到的,评论URL应该是评论消息的一部分,让我们现在添加它:
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
——/ src /信息/ CommentMessage.php+ + + b / src /信息/ CommentMessage.php@@ -6,10 +6,16 @@类注释消息{公共函数__construct(私有int $id+私有字符串$reviewUrl,私有数组$context = [],) {}+公共函数getReviewUrl():字符串+ {+返回$this->reviewUrl;+}+公共函数getId(): int{返回$this->id;
最后,更新控制器以生成评审URL,并将其传递给注释消息构造函数:
12 34 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
——/ src /控制器/ AdminController.php+ + + b / src /控制器/ AdminController.php@@ Symfony\Component\Hob娱乐下载ttpKernel\ httpache \StoreInterface;使用Syob娱乐下载mfony \ \ HttpKernel \ KernelInterface组件;使用Syob娱乐下载mfony \组件\ \ MessageBusInterface使者;使用Syob娱乐下载mfony \组件\路由\注释\路线;+使用Syob娱乐下载mfony \组件\ \发电机\ UrlGeneratorInterface路由;使用Syob娱乐下载mfony \工作流组件\ \ WorkflowInterface;用树枝\环境;@@类AdminController extends AbstractController $this->entityManager->flush();如果($accepted) {- $this->bus->dispatch(new CommentMessage($comment->getId()));+ $reviewUrl = $this->generateUrl('review_comment', ['id' => $comment->getId()], UrlGeneratorInterface::ABSOLUTE_URL);+ $this->总线->调度(新的评论消息($comment->getId(), $reviewUrl));}返回新的响应($this->twig->渲染('admin/review.html。嫩枝”,(——/ src /控制器/ ConferenceController.php+ + + b / src /控制器/ ConferenceController.php@@ -18,6 +18,7使用Symfonob娱乐下载y\Component\Messenger\MessageBusInterface;使用Syob娱乐下载mfony \组件\ \通知\通知通知;使用Syob娱乐下载mfony \ \通知\ NotifierInterface组件;使用Syob娱乐下载mfony \组件\路由\注释\路线;+使用Syob娱乐下载mfony \组件\ \发电机\ UrlGeneratorInterface路由;class ConferenceController extends AbstractController {@@ -75,7 +76,8 @@ class ConferenceController extends AbstractController 'referrer' => $request->headers->get('referer'), 'permalink' => $request->getUri(),];- $this->bus->dispatch(new CommentMessage($comment->getId(), $context));+ $reviewUrl = $this->generateUrl('review_comment', ['id' => $comment->getId()], UrlGeneratorInterface::ABSOLUTE_URL);+ $this->总线->调度(新的评论消息($comment->getId(), $reviewUrl, $context));$notifier->send(新的通知('谢谢你的反馈;您的评论将在审核后发布。”,(“浏览器”)));
代码解耦意味着在更多的地方进行更改,但它使测试、推理和重用变得更容易。
再试一次,现在信息应该已经很好了:
全面采用异步模式
默认情况下,通知是异步发送的,就像电子邮件:
如果要禁用异步消息,就会遇到一个小问题。对于每一条评论,我们都会收到一封电子邮件和一条Slack消息。如果Slack消息错误(错误的通道id,错误的令牌,…),消息将被重试三次,然后才会被丢弃。但由于电子邮件先发送,我们将收到3封电子邮件,没有Slack消息。
一旦一切都是异步的,消息就变得独立了。短信已经配置为异步,以防你也想在手机上收到通知。