Создание и отправка уведомлений

Дата обновления перевода 2023-01-16

Создание и отправка уведомлений

Установка

Современные веб-приложения используют много каналов для отправки сообщений пользователям (такие как 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;
  • Browser канал использует flash-сообщения .
  • Push канал отправляет уведомления на телефоны и браузеры через пуш-уведомления.

Tip

Используйте секреты для безопасного хранения ваших API-токенов.

SMS-канал

Caution

Если любое из значений DSN содержит любой символ, считающийся специальным в URI (такой как +, @, $, #, /, :, *, !), вы должны зашифровать его. См. RFC 3986, чтобы увидеть полный список зарезервированных символов, или используйте функцию urlencode, чтобы зашифровать их.

SMS канал использует классы Texter для отправки SMS-сообщений на мобильные телефоны. Эта функция требует подписки на внешние сервисы, которые отправляют SMS-сообщения. Symfony предоставляет интеграцию с несколькими популярными SMS-сервисами:

6.1

Интегррации 46elks, OrangeSms, KazInfoTeh и Sendberry были представлены в Symfony 6.1. Опция no_stop_clause в DSN OvhCloud была представлена в Symfony 6.1. Опция test в DSN Smsapi была представлена в Symfony 6.1.

6.2

Интеграции ContactEveryone и SMSFactor были представлены в Symfony 6.2.

Для включения texter, добавьте корректный DSN в ваш .env файл и настройте texter_transports:

1
2
# .env
TWILIO_DSN=twilio://SID:TOKEN@default?from=FROM
  • YAML
  • XML
  • PHP
1
2
3
4
5
# config/packages/notifier.yaml
framework:
    notifier:
        texter_transports:
            twilio: '%env(TWILIO_DSN)%'

Чат-канал

Caution

Если любое из значений DSN содержит любой символ, считающийся специальным в URI (такой как +, @, $, #, /, :, *, !), вы должны зашифровать его. См. RFC 3986, чтобы увидеть полный список зарезервированных символов, или используйте функцию urlencode, чтобы зашифровать их.

Чат-канал используется для отправки сообщений пользователям в чаты используя классы Chatter. Symfony предоставляет интеграцию с этими сервисами чатов:

?????? ????? DSN
AmazonSns symfony/amazon-sns-notifier sns://ACCESS_KEY:SECRET_KEY@default?region=REGION
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
LinkedIn symfony/linked-in-notifier linkedin://TOKEN:USER_ID@default
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
Zendesk symfony/zendesk-notifier zendesk://EMAIL:TOKEN@SUBDOMAIN
Zulip symfony/zulip-notifier zulip://EMAIL:TOKEN@HOST?channel=CHANNEL

6.2

Интеграции Zendesk и Chatwork были представлены в Symfony 6.2.

Chatters конфигурируются с помощью настройки chatter_transports:

1
2
# .env
SLACK_DSN=slack://TOKEN@default?channel=CHANNEL
  • YAML
  • XML
  • PHP
1
2
3
4
5
# config/packages/notifier.yaml
framework:
    notifier:
        chatter_transports:
            slack: '%env(SLACK_DSN)%'

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 с которого будут приходить письма-уведомления:

  • YAML
  • XML
  • PHP
1
2
3
4
5
6
# config/packages/mailer.yaml
framework:
    mailer:
        dsn: '%env(MAILER_DSN)%'
        envelope:
            sender: 'notifications@example.com'

Пуш-канал

Caution

Если любое из значений DSN содержит любой символ, считающийся специальным в URI (такой как +, @, $, #, /, :, *, !), вы должны зашифровать его. См. RFC 3986, чтобы увидеть полный список зарезервированных символов, или используйте функцию urlencode, чтобы зашифровать их.

Пуш-канал используется для отправки пользователям уведомлений с использованием классов Texter. Symfony предоставляет интеграцию с этими пуш-сервисами:

?????? ????? DSN
Engagespot symfony/engagespot-notifier engagespot://API_KEY@default?campaign_name=CAMPAIGN_NAME
Expo symfony/expo-notifier expo://Token@default
OneSignal symfony/one-signal-notifier onesignal://APP_ID:API_KEY@default?defaultRecipientId=DEFAULT_RECIPIENT_ID''

6.1

Интеграция Engagespot была представлена в Symfony 6.1.

Чтобы включить texter, добавьте правильную DSN в ваш файл .env, и сконфигурируйте texter_transports:

1
2
# .env
EXPO_DSN=expo://TOKEN@default
  • YAML
  • XML
  • PHP
1
2
3
4
5
# config/packages/notifier.yaml
framework:
    notifier:
        texter_transports:
            expo: '%env(EXPO_DSN)%'

Настройка использования резервного транспорта или Round-Robin

Кроме настройки одного или нескольких отдельных транспортов вы также можете использовать специальные символы || и && для реализации резервного или round-robin транспорта:

  • YAML
  • XML
  • PHP
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)
    {
        // ...

        // Создать уведомление, которое отправится
        // через "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
Получатель по умолчанию, который полезен, когда не нужно иметь информацию о получателе. Например, канал browser использует flashbag сессии текущего request;
Recipient
Может содержать и email и телефон пользователя. Этот получатель может использоваться для всех каналов (зависит от того установлены ли они действительно).

Конфигурация политики каналов

Вместо указания целевых каналов при создании Symfony также позволяет вам использовать уровни важности уведомлений. Обновите конфигурацию для указания какие каналы должны использоваться для нужных уровней (используя channel_policy):

  • YAML
  • XML
  • PHP
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)
    {
        // ...

        $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
26
27
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
{
    private $price;

    public function __construct(int $price)
    {
        $this->price = $price;
    }

    public function getChannels(RecipientInterface $recipient)
    {
        if (
            $this->price > 10000
            && $recipient instanceof SmsRecipientInterface
        ) {
            return ['sms'];
        }

        return ['email'];
    }
}

Настройка сообщений уведомлений

У каждого канала есть собственный интерфейс уведомлений, который вы можете реализовать для настройки сообщений уведомлений. Например, если вы хотите изменить сообщение на основе сервиса chat, реализуйте 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
29
30
// 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\SmsRecipientInterface;

class InvoiceNotification extends Notification implements ChatNotificationInterface
{
    private $price;

    public function __construct(int $price)
    {
        $this->price = $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 для изменения сообщений, отправляемых по этим каналам.

Настройка уведомлений браузера (флеш-сообщения)

6.1

Поддержка настройки уровней важности была представлена в Symfony 6.1.

Поведение по умолчанию для уведомлений канала браузера - добавлять флеш-сообщений с notification в качестве ключа.

Однако, вы можете предпочесть связать уровень важности уведомления с типом флеш- сообщения, чтобы вы могли настроить их стиль.

Вы можете сделать это, переопределив сервис по умолчанию notifier.flash_message_importance_mapper на вашу собственную реализацию FlashMessageImportanceMapperInterface, где вы можете предоставить собственную "важность" отображению "уровня предупреждения".

На данный момент, Symfony предоставаляет реализацию для типичных уровней предупреждния фреймворка начальной загузки CSS, которые вы можете реализовать немедленно, используя:

  • YAML
  • XML
  • PHP
1
2
3
4
# config/services.yaml
services:
    notifier.flash_message_importance_mapper:
        class: Symfony\Component\Notifier\FlashMessage\BootstrapFlashMessageImportanceMapper

Отключение доставки

Во время разработки и тестирования вы можете захотеть полностью отключить отправку уведомлений. Вы можете сделать это, дав 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'
.. TODO
  • Использование автобуса сообщений для асинхронных уведомлений
  • Описать обработчик увледомлений monolog
  • Описать интеграцию notification_on_failed_messages