Створення та відправлення сповіщень
Дата оновлення перекладу 2024-06-10
Створення та відправлення сповіщень
Установка
Сучасні веб-додатки використовують багато каналів для відправлення повідомлень користувачам (такі як SMS, повідомлення в Slack, email, push-повідомлення та ін.). Компонент Symfony Notifier - це абстракція над усіма цими каналами. Він надає динамічний спосіб керування тим, як відправляються повідомлення. Встановіть Notifier за допомогою:
1
$ composer require symfony/notifier
Канали: Chatters, Texters, Email, Browser і Push
Компонент Notifier може відправляти сповіщення різними каналами. Кожний канал може за допомогою транспортів інтегруватися з різними постачальниками (наприклад, Slack або Twilio SMS).
Компонент Notifier підтримує такі канали:
- SMS-канал відправляє сповіщення на телефони SMS-повідомленнями;
- Чат-канал відправляє сповіщення у чат-сервіси, такі як Slack і Telegram;
- Email-канал інтегрується з Symfony Mailer;
- Браузер-канал використовує флеш-повідомлення .
- Push-канал відправляє сповіщення на телефони та браузери через пуш-сповіщення.
Tip
Використовуйте секрети для безпечного зберігання ваших API-токенів.
SMS-канал
Caution
Якщо будь-яке зі значень DSN містить будь-який символ, який вважається спеціальним
в URI (на кшталт, as +
, @
, $
, #
, /
, :
, *
, !
), ви
повинні зашифрувати їх. Див. RFC 3986, щоб побачити повний перелік зарезервованих
символів, або використайте функцію urlencode, щоб зашифрувати їх.
SMS-канал використовує класи Texter для відправлення SMS-повідомлень на мобільні телефони. Ця функція вимагає підписки на зовнішні сервіси, які відправляють SMS-повідомлення. Symfony надає інтеграцію з декількома популярними SMS-сервісами:
Tip
Деякі сторонні транспорти, при використанні API, підтримують зворотні виклики статусу через веб-хуки. Дивіться Документацію про веб-хуки для отримання додаткової інформації.
7.1
Інтеграція Sms77 застаріла, починаючи з Symfony 7.1, натомість використовуйте інтеграцію Seven.io.
Для ввімкнення texter, додайте коректний DSN у ваш файл .env
та налаштуйте
texter_transports
:
1 2
# .env
TWILIO_DSN=twilio://SID:TOKEN@default?from=FROM
1 2 3 4 5
# config/packages/notifier.yaml
framework:
notifier:
texter_transports:
twilio: '%env(TWILIO_DSN)%'
Клас TexterInterface дозволяє вам відправляти SMS-повідомлення:
1 2 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 30 31
// src/Controller/SecurityController.php
namespace App\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Notifier\Message\SmsMessage;
use Symfony\Component\Notifier\TexterInterface;
use Symfony\Component\Routing\Attribute\Route;
class SecurityController
{
#[Route('/login/success')]
public function loginSuccess(TexterInterface $texter): Response
{
$options = (new ProviderOptions())
->setPriority('high')
;
$sms = new SmsMessage(
// номер телефону, на який потрібно відправити SMS
'+1411111111',
// повідомлення
'A new login was detected!',
// опціонально, ви можете перевизначити "from", визначене за замовчуванням у транспорті
'+1422222222',
);
$sentMessage = $texter->send($sms);
// ...
}
}
Метод send()
повертає змінну типу SentMessage,
яка надає інформацію на кшталт ID повідомлення та оригінального змісту повідомлення.
Чат-канал
Caution
Якщо будь-яке зі значень DSN містить будь-який символ, який вважається спеціальним
в URI (на кшталт, as +
, @
, $
, #
, /
, :
, *
, !
), ви
повинні зашифрувати їх. Див. RFC 3986, щоб побачити повний перелік зарезервованих
символів, або використайте функцію urlencode, щоб зашифрувати їх.
Канал чатів використовується для відправлення повідомлень користувачам у чати, використовуючи класи Chatter. Symfony надає інтеграцію з цими сервісами чатів:
?????? | ????? | DSN |
---|---|---|
AmazonSns | symfony/amazon-sns-notifier |
sns://ACCESS_KEY:SECRET_KEY@default?region=REGION |
Bluesky | symfony/bluesky-notifier |
bluesky://USERNAME:PASSWORD@default |
Chatwork | symfony/chatwork-notifier |
chatwork://API_TOKEN@default?room_id=ID |
Discord | symfony/discord-notifier |
discord://TOKEN@default?webhook_id=ID |
FakeChat | symfony/fake-chat-notifier |
fakechat+email://default?to=TO&from=FROM or fakechat+logger://default |
Firebase | symfony/firebase-notifier |
firebase://USERNAME:PASSWORD@default |
Gitter | symfony/gitter-notifier |
gitter://TOKEN@default?room_id=ROOM_ID |
GoogleChat | symfony/google-chat-notifier |
googlechat://ACCESS_KEY:ACCESS_TOKEN@default/SPACE?thread_key=THREAD_KEY |
LINE Notify | symfony/line-notify-notifier |
linenotify://TOKEN@default |
symfony/linked-in-notifier |
linkedin://TOKEN:USER_ID@default |
|
Mastodon | symfony/mastodon-notifier |
mastodon://ACCESS_TOKEN@HOST |
Mattermost | symfony/mattermost-notifier |
mattermost://ACCESS_TOKEN@HOST/PATH?channel=CHANNEL |
Mercure | symfony/mercure-notifier |
mercure://HUB_ID?topic=TOPIC |
MicrosoftTeams | symfony/microsoft-teams-notifier |
microsoftteams://default/PATH |
RocketChat | symfony/rocket-chat-notifier |
rocketchat://TOKEN@ENDPOINT?channel=CHANNEL |
Slack | symfony/slack-notifier |
slack://TOKEN@default?channel=CHANNEL |
Telegram | symfony/telegram-notifier |
telegram://TOKEN@default?channel=CHAT_ID |
symfony/twitter-notifier |
twitter://API_KEY:API_SECRET:ACCESS_TOKEN:ACCESS_SECRET@default |
|
Zendesk | symfony/zendesk-notifier |
zendesk://EMAIL:TOKEN@SUBDOMAIN |
Zulip | symfony/zulip-notifier |
zulip://EMAIL:TOKEN@HOST?channel=CHANNEL |
7.1
Інтеграції Bluesky
, Unifonic
та Smsbox
були представлені
в Symfony 7.1.
Caution
By default, if you have the Messenger component installed, the notifications will be sent through the MessageBus. If you don't have a message consumer running, messages will never be sent.
To change this behavior, add the following configuration to send messages directly via the transport:
1 2 3 4
# config/packages/notifier.yaml
framework:
notifier:
message_bus: false
Chatters конфігуруються за допомогою налаштування chatter_transports
:
1 2
# .env
SLACK_DSN=slack://TOKEN@default?channel=CHANNEL
1 2 3 4 5
# config/packages/notifier.yaml
framework:
notifier:
chatter_transports:
slack: '%env(SLACK_DSN)%'
Клас ChatterInterface дозволяє вам відправляти повідомлення у чат-сервісах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
// src/Controller/CheckoutController.php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Notifier\ChatterInterface;
use Symfony\Component\Notifier\Message\ChatMessage;
use Symfony\Component\Routing\Attribute\Route;
class CheckoutController extends AbstractController
{
#[Route('/checkout/thankyou')]
public function thankyou(ChatterInterface $chatter): Response
{
$message = (new ChatMessage('You got a new invoice for 15 EUR.'))
// якщо не встановлено чітко, повідомлення відправляється
// транспорту за замовчуванням (першому сконфігурованому)
->transport('slack');
$sentMessage = $chatter->send($message);
// ...
}
}
Метод send()
повертає змінну типу SentMessage,
яка надає інформацію на кшталт ID повідомлення та оригінального змісту повідомлення.
Email-канал
Email-канал використовує Symfony Mailer для відправлення сповіщень, використовуючи спеціальний NotificationEmail. Необхідно встановити Twig bridge разом з Inky та Twig розширенням CSS Inliner:
1
$ composer require symfony/twig-pack twig/cssinliner-extra twig/inky-extra
Після цього налаштуйте mailer . Ви також можете налаштувати адресу email з якої будуть приходити листи-сповіщення:
1 2 3 4 5 6
# config/packages/mailer.yaml
framework:
mailer:
dsn: '%env(MAILER_DSN)%'
envelope:
sender: 'notifications@example.com'
Push-канал
Caution
Якщо будь-яке зі значень DSN містить будь-який символ, який вважається спеціальним
в URI (на кшталт, as +
, @
, $
, #
, /
, :
, *
, !
), ви
повинні зашифрувати їх. Див. RFC 3986, щоб побачити повний перелік зарезервованих
символів, або використайте функцію urlencode, щоб зашифрувати їх.
Push-канал використовується для відправлення користувачам сповіщень з використанням класів Texter. Symfony надає інтеграцію з цими пуш-сервісами:
?????? | ????? | DSN |
---|---|---|
Engagespot | symfony/engagespot-notifier |
engagespot://API_KEY@default?campaign_name=CAMPAIGN_NAME |
Expo | symfony/expo-notifier |
expo://Token@default |
Novu | symfony/novu-notifier |
novu://API_KEY@default |
Ntfy | symfony/ntfy-notifier |
ntfy://default/TOPIC |
OneSignal | symfony/one-signal-notifier |
onesignal://APP_ID:API_KEY@default?defaultRecipientId=DEFAULT_RECIPIENT_ID |
PagerDuty | symfony/pager-duty-notifier |
pagerduty://TOKEN@SUBDOMAIN |
Pushover | symfony/pushover-notifier |
pushover://USER_KEY:APP_TOKEN@default |
Pushy | symfony/pushy-notifier |
pushy://API_KEY@default |
Щоб увімкнути texter, додайте правильну DSN у ваш файл .env
, та
сконфігуруйте texter_transports
:
7.1
Інтеграція Pushy була представлена в Symfony 7.1.
1 2
# .env
EXPO_DSN=expo://TOKEN@default
1 2 3 4 5
# config/packages/notifier.yaml
framework:
notifier:
texter_transports:
expo: '%env(EXPO_DSN)%'
Конфігурація резервного транспорту або балансування Round-Robin
Окрім налаштування одного або декількох окремих транспортів, ви також можете викоритовувати
спеціальні символи ||
і &&
для реалізації резервного або round-robin транспорту:
1 2 3 4 5 6 7 8 9 10
# config/packages/notifier.yaml
framework:
notifier:
chatter_transports:
# Відправляти сповіщення в Slack та використовувати Telegram, якщо
# Slack видав помилку
main: '%env(SLACK_DSN)% || %env(TELEGRAM_DSN)%'
# Відправляти сповіщення використовуючи наступний запланований транспорт, розрахований методом round robin
roundrobin: '%env(SLACK_DSN)% && %env(TELEGRAM_DSN)%'
Створення та відправлення сповіщень
Для відправлення сповіщення, автоматично підключіть
NotifierInterface (ID сервісу -
notifier
). У цього класу є метод send()
, який дозволяє вам відправляти сповіщення
Notification отримувачу
Recipient:
1 2 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 30 31
// src/Controller/InvoiceController.php
namespace App\Controller;
use Symfony\Component\Notifier\Notification\Notification;
use Symfony\Component\Notifier\NotifierInterface;
use Symfony\Component\Notifier\Recipient\Recipient;
class InvoiceController extends AbstractController
{
#[Route('/invoice/create')]
public function create(NotifierInterface $notifier): Response
{
// ...
// Створити сповіщення, яке відправиться
// через "email" канал
$notification = (new Notification('New Invoice', ['email']))
->content('You got a new invoice for 15 EUR.');
// Отримувач сповіщення
$recipient = new Recipient(
$user->getEmail(),
$user->getPhonenumber()
);
// Відправити сповіщення отримувачу
$notifier->send($notification, $recipient);
// ...
}
}
Сповіщення Notification
створюється з 2 аргументами: тема та канали.
Канали вказують, який канал або транспорт має використовуватися для відправлення
сповіщення. Наприклад, ['email', 'sms']
відправлять і email, і sms-сповіщення
користувачу.
Сповіщення за замовчуванням також має методи content()
і emoji()
, щоб
встановлювати зміст та іконку змісту.
Symfony надає таких отримувачів:
- NoRecipient
- Отримувач за замовчуванням, який корисний, коли не треба мати інформацію про отримувача. Наприклад, браузер-канал використовує flashbag сесії поточного запиту;
- Recipient
- Може містити і email, і телефон користувача. Цей отримувач може використовуватися для всіх каналів (залежить від того, чи дійсно вони встановлені).
Конфігурація політики каналів
Замість вказування цільових каналів при створенні, Symfony також дозволяє вам
використовувати рівні важливості сповіщень. Оновіть конфігурацію для вказання,
які канали мають використовуватися для потрібних рівнів (використовуючи
channel_policy
):
1 2 3 4 5 6 7 8 9 10 11 12 13 14
# config/packages/notifier.yaml
framework:
notifier:
# ...
channel_policy:
# Використовувати SMS, Slack і email для термінових сповіщень
urgent: ['sms', 'chat/slack', 'email']
# Використовувати Slack для важливих сповіщень
high: ['chat/slack']
# Використовувати браузер для сповіщень середнього та низкього рівнів
medium: ['browser']
low: ['browser']
Тепер, коли важливість сповіщення встановлена як "high", воно буде відправлене через транспорт Slack:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// ...
class InvoiceController extends AbstractController
{
#[Route('/invoice/create')]
public function invoice(NotifierInterface $notifier): Response
{
// ...
$notification = (new Notification('New Invoice'))
->content('You got a new invoice for 15 EUR.')
->importance(Notification::IMPORTANCE_HIGH);
$notifier->send($notification, new Recipient('wouter@example.com'));
// ...
}
}
Користувацьке налаштування сповіщень
Ви можете розширити базові класи Notification
або Recipient
для
налаштування їх поведінки. Наприклад, ви можете перевизначити метод
getChannels()
, щоб повертати sms
лише якщо сума рахунку дуже
велика і в отримувача є телефонний номер:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
namespace App\Notifier;
use Symfony\Component\Notifier\Notification\Notification;
use Symfony\Component\Notifier\Recipient\RecipientInterface;
use Symfony\Component\Notifier\Recipient\SmsRecipientInterface;
class InvoiceNotification extends Notification
{
public function __construct(
private int $price,
) {
}
public function getChannels(RecipientInterface $recipient): array
{
if (
$this->price > 10000
&& $recipient instanceof SmsRecipientInterface
) {
return ['sms'];
}
return ['email'];
}
}
Користувацьке налаштування повідомлень сповіщень
У кожного каналу є власний інтерфейс сповіщень, який ви можете реалізувати для налаштування
повідомлень сповіщень. Наприклад, якщо ви хочете змінити повідомлення на основі чат-сервісу,
реалізуйте ChatNotificationInterface
та його метод asChatMessage()
:
1 2 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
// src/Notifier/InvoiceNotification.php
namespace App\Notifier;
use Symfony\Component\Notifier\Message\ChatMessage;
use Symfony\Component\Notifier\Notification\ChatNotificationInterface;
use Symfony\Component\Notifier\Notification\Notification;
use Symfony\Component\Notifier\Recipient\RecipientInterface;
class InvoiceNotification extends Notification implements ChatNotificationInterface
{
public function __construct(
private int $price,
) {
}
public function asChatMessage(RecipientInterface $recipient, string $transport = null): ?ChatMessage
{
// Додайте свій emoji, якщо повідомлення надсилається в Slack
if ('slack' === $transport) {
return (new ChatMessage('You\'re invoiced '.$this->price.' EUR.'))
->emoji('money');
}
// Якщо ви повернете null, Notifier створить ChatMessage
// так, якщо б цього методу не було
return null;
}
}
Також є інтерфейси SmsNotificationInterface, EmailNotificationInterface та EmailNotificationInterface для зміни повідомлень, що надсилаються по цих каналах.
Користувацьке налаштування сповіщень браузера (флеш-повідомлення)
Поведінка сповіщень каналу браузера за замовчуванням - додавати
флеш-повідомлення з notification
в якості ключа.
Однак, ви можете захотіти вказати рівень важливості сповіщення типу флеш-повідомлення, щоб ви могли підлаштувати їх стиль.
Ви можете зробити це, перевизначивши сервіс за замовчуванням
notifier.flash_message_importance_mapper
на вашу власну реалізацію
FlashMessageImportanceMapperInterface,
де ви можете надати вашу власну "важливість" як "рівень небезпеки".
На даний момент Symfony надає реалізацію для типових рівнів небезпеки для CSS фреймворку Bootstrap, які ви можете реалізувати негайно, використавши:
1 2 3 4
# config/services.yaml
services:
notifier.flash_message_importance_mapper:
class: Symfony\Component\Notifier\FlashMessage\BootstrapFlashMessageImportanceMapper
Тестування Notifier
Symfony надає NotificationAssertionsTrait, які надають корисні методи для тестування вашої реалізації Notifier. Ви можете отримати переваги цього класу, використовуючи його напряму, або розширивши KernelTestCase.
Див. документацію тестування , щоб побачити список доступних тверджень.
Відключення доставки
Під час розробки та тестування ви можете захотіти повністю відключити відправлення сповіщень.
Ви можете зробити це, надавши Notifier транспорт NullTransport
для всіх налаштованих
транспортів texter та chatter, але лише для dev
(та/або test
) середовищ:
1 2 3 4 5 6 7
# config/packages/dev/notifier.yaml
framework:
notifier:
texter_transports:
twilio: 'null://null'
chatter_transports:
slack: 'null://null'
Використання подій
Клас Transport` компонента Notifier дозволяє вам опціонально підключатися до життєвого циклу через події.
Подія MessageEvent::class
Типові цілі: Зробити щось до відправки повідомлення (на кшталт логування того, яке повідомлення буде відправлено або відображення чогось про подію, яка буде виконана).
Прямо перед відправкою повідомлення, оголошується клас події MessageEvent
.
Слухачі отримують подію MessageEvent:
1 2 3 4 5 6 7 8 9
use Symfony\Component\Notifier\Event\MessageEvent;
$dispatcher->addListener(MessageEvent::class, function (MessageEvent $event) {
// отримує екземпляр повідомлення
$message = $event->getMessage();
// логувати щось
$this->logger(sprintf('Message with subject: %s will be send to %s, $message->getSubject(), $message->getRecipientId()'));
});
Подія FailedMessageEvent
Типові цілі: Зробити щось перед тим, як буде викликано виключення (повторно спробувати відправити повідомлення або записати лог додаткової інформації).
Кожен раз, коли викликається виключення під час відправки повідомлення, оголошується
клас події FailedMessageEvent
. Слухач може зробити щось корисне до того, як буде
викликане виключення.
Слухачі отримують подію FailedMessageEvent:
1 2 3 4 5 6 7 8 9 10 11 12
use Symfony\Component\Notifier\Event\FailedMessageEvent;
$dispatcher->addListener(FailedMessageEvent::class, function (FailedMessageEvent $event) {
// отримує екземпляр повідомлення
$message = $event->getMessage();
// отримує екземпляр помилки
$error = $event->getError();
// логувати щось
$this->logger(sprintf('The message with subject: %s has not been sent successfully. The error is: %s, $message->getSubject(), $error->getMessage()'));
});
Подія SentMessageEvent
Типові цілі: Виконати якусь дію, якщо повідомлення було відправлено успішно
(на кшталт отримання id, поверненого при відправці повідомлення).
Після того, як повідомлення було успішно відправено, оголошується клас події
SentMessageEvent
. Слухачі отримують подію SentMessageEvent:
1 2 3 4 5 6 7 8 9
use Symfony\Component\Notifier\Event\SentMessageEvent;
$dispatcher->addListener(SentMessageEvent::class, function (SentMessageEvent $event) {
// отримує екземпляр повідомлення
$message = $event->getOriginalMessage();
// логувати щось
$this->logger(sprintf('The message has been successfully sent and has id: %s, $message->getMessageId()'));
});