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

Дата обновления перевода 2025-02-12

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

Установка

Современные веб-приложения используют много каналов для отправки сообщений пользователям (такие как SMS, сообщения в Slack, email, push-уведомления и другие). Symfony-компонент Notifier - это абстракция над всеми этими каналами. Он предоставляет динамический способ управления как отправляются сообщения. Установите Notifier с помощью:

1
$ composer require symfony/notifier

Каналы

Каналы - это различные средства, через которые могут доставляться уведомления.
К таким каналам относятся email, SMS, чат-сервисы, пуш-уведомления и т. д. Каждый канал канал может интегрироваться с различными поставщиками (например, Slack или Twilio SMS) с помощью транспорта.

Комонент Notifier поддерживает такие каналы:

  • SMS-канал отправляет уведомления на телефоны SMS-сообщениями;
  • Чат-канал отправляет уведомления в чат-сервисы как Slack и Telegram;
  • Email-канал интегрируется с Symfony Mailer;
  • Канал браузера использует flash-сообщения .
  • Пуш-канал отправляет уведомления на телефоны и браузеры через пуш-уведомления.
  • Декстоп-канал отображает уведомления на рабочем столе той же машины.

7.2

Канал Desktop был представлен в Symfony 7.2.

SMS-канал

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

Warning

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

??????  
46elks ?????????: composer require symfony/forty-six-elks-notifier
DSN: forty-six-elks://API_USERNAME:API_PASSWORD@default?from=FROM
????????? ???-?????: ???
AllMySms ?????????: composer require symfony/all-my-sms-notifier
DSN: allmysms://LOGIN:APIKEY@default?from=FROM
????????? ???-?????: ???
AmazonSns ?????????: composer require symfony/amazon-sns-notifier
DSN: sns://ACCESS_KEY:SECRET_KEY@default?region=REGION
????????? ???-?????: ???
Bandwidth ?????????: composer require symfony/bandwidth-notifier
DSN: bandwidth://USERNAME:PASSWORD@default?from=FROM&account_id=ACCOUNT_ID&application_id=APPLICATION_ID&priority=PRIORITY
????????? ???-?????: ???
Brevo ?????????: composer require symfony/brevo-notifier
DSN: brevo://API_KEY@default?sender=SENDER
????????? ???-?????: ???
Clickatell ?????????: composer require symfony/clickatell-notifier
DSN: clickatell://ACCESS_TOKEN@default?from=FROM
????????? ???-?????: ???
ContactEveryone ?????????: composer require symfony/contact-everyone-notifier
DSN: contact-everyone://TOKEN@default?&diffusionname=DIFFUSION_NAME&category=CATEGORY
????????? ???-?????: ???
Esendex Install: composer require symfony/esendex-notifier
DSN: esendex://USER_NAME:PASSWORD@default?accountreference=ACCOUNT_REFERENCE&from=FROM
????????? ???-?????: ???
FakeSms ?????????: composer require symfony/fake-sms-notifier
DSN: fakesms+email://MAILER_SERVICE_ID?to=TO&from=FROM or fakesms+logger://default
????????? ???-?????: ???
FreeMobile ?????????: composer require symfony/free-mobile-notifier
DSN: freemobile://LOGIN:API_KEY@default?phone=PHONE
????????? ???-?????: ???
GatewayApi ?????????: composer require symfony/gateway-api-notifier
DSN: gatewayapi://TOKEN@default?from=FROM
????????? ???-?????: ???
GoIP ?????????: composer require symfony/go-ip-notifier
DSN: goip://USERNAME:PASSWORD@HOST:80?sim_slot=SIM_SLOT
????????? ???-?????: ???
Infobip ?????????: composer require symfony/infobip-notifier
DSN: infobip://AUTH_TOKEN@HOST?from=FROM
????????? ???-?????: ???
Iqsms ?????????: composer require symfony/iqsms-notifier
DSN: iqsms://LOGIN:PASSWORD@default?from=FROM
????????? ???-?????: ???
iSendPro ?????????: composer require symfony/isendpro-notifier
DSN: isendpro://ACCOUNT_KEY_ID@default?from=FROM&no_stop=NO_STOP&sandbox=SANDBOX
????????? ???-?????: ???
KazInfoTeh ?????????: composer require symfony/kaz-info-teh-notifier
DSN: kaz-info-teh://USERNAME:PASSWORD@default?sender=FROM
????????? ???-?????: ???
LightSms ?????????: composer require symfony/light-sms-notifier
DSN: lightsms://LOGIN:TOKEN@default?from=PHONE
????????? ???-?????: ???
LOX24 ?????????: composer require symfony/lox24-notifier
DSN: lox24://USER:TOKEN@default?from=FROM
????????? ???-?????: ???
Mailjet ?????????: composer require symfony/mailjet-notifier
DSN: mailjet://TOKEN@default?from=FROM
????????? ???-?????: ???
MessageBird ?????????: composer require symfony/message-bird-notifier
DSN: messagebird://TOKEN@default?from=FROM
????????? ???-?????: ???
MessageMedia ?????????: composer require symfony/message-media-notifier
DSN: messagemedia://API_KEY:API_SECRET@default?from=FROM
????????? ???-?????: ???
Mobyt ?????????: composer require symfony/mobyt-notifier
DSN: mobyt://USER_KEY:ACCESS_TOKEN@default?from=FROM
????????? ???-?????: ???
Nexmo ?????????: composer require symfony/nexmo-notifier
???????? ? ?????? Vonage (??. ????)
Octopush ?????????: composer require symfony/octopush-notifier
DSN: octopush://USERLOGIN:APIKEY@default?from=FROM&type=TYPE
????????? ???-?????: ???
OrangeSms ?????????: composer require symfony/orange-sms-notifier
DSN: orange-sms://CLIENT_ID:CLIENT_SECRET@default?from=FROM&sender_name=SENDER_NAME
????????? ???-?????: ???
OvhCloud ?????????: composer require symfony/ovh-cloud-notifier
DSN: ovhcloud://APPLICATION_KEY:APPLICATION_SECRET@default?consumer_key=CONSUMER_KEY&service_name=SERVICE_NAME
????????? ???-?????: ???
Plivo ?????????: composer require symfony/plivo-notifier
DSN: plivo://AUTH_ID:AUTH_TOKEN@default?from=FROM
????????? ???-?????: ???
Primotexto ?????????: composer require symfony/primotexto-notifier
DSN: primotexto://API_KEY@default?from=FROM
????????? ???-?????: ???
Redlink ?????????: composer require symfony/redlink-notifier
DSN: redlink://API_KEY:APP_KEY@default?from=SENDER_NAME&version=API_VERSION
????????? ???-?????: ???
RingCentral ?????????: composer require symfony/ring-central-notifier
DSN: ringcentral://API_TOKEN@default?from=FROM
????????? ???-?????: ???
Sendberry ?????????: composer require symfony/sendberry-notifier
DSN: sendberry://USERNAME:PASSWORD@default?auth_key=AUTH_KEY&from=FROM
????????? ???-?????: ???
Sendinblue ?????????: composer require symfony/sendinblue-notifier
DSN: sendinblue://API_KEY@default?sender=PHONE
????????? ???-?????: ???
Sms77 ?????????: composer require symfony/sms77-notifier
DSN: sms77://API_KEY@default?from=FROM
????????? ???-?????: ???
SimpleTextin ?????????: composer require symfony/simple-textin-notifier
DSN: simpletextin://API_KEY@default?from=FROM
????????? ???-?????: ???
Sinch ?????????: composer require symfony/sinch-notifier
DSN: sinch://ACCOUNT_ID:AUTH_TOKEN@default?from=FROM
????????? ???-?????: ???
Sipgate ?????????: composer require symfony/sipgate-notifier
DSN: sipgate://TOKEN_ID:TOKEN@default?senderId=SENDER_ID
????????? ???-?????: ???
SmsSluzba ?????????: composer require symfony/sms-sluzba-notifier
DSN: sms-sluzba://USERNAME:PASSWORD@default
????????? ???-?????: ???
Smsapi ?????????: composer require symfony/smsapi-notifier
DSN: smsapi://TOKEN@default?from=FROM
????????? ???-?????: ???
Smsbox ?????????: composer require symfony/smsbox-notifier
DSN: smsbox://APIKEY@default?mode=MODE&strategy=STRATEGY&sender=SENDER
????????? ???-?????: ???
SmsBiuras ?????????: composer require symfony/sms-biuras-notifier
DSN: smsbiuras://UID:API_KEY@default?from=FROM&test_mode=0
????????? ???-?????: ???
Smsc ?????????: composer require symfony/smsc-notifier
DSN: smsc://LOGIN:PASSWORD@default?from=FROM
????????? ???-?????: ???
SMSense ?????????: composer require smsense-notifier
DSN: smsense://API_TOKEN@default?from=FROM
????????? ???-?????: ???
SMSFactor ?????????: composer require symfony/sms-factor-notifier
DSN: sms-factor://TOKEN@default?sender=SENDER&push_type=PUSH_TYPE
????????? ???-?????: ???
SpotHit ?????????: composer require symfony/spot-hit-notifier
DSN: spothit://TOKEN@default?from=FROM
????????? ???-?????: ???
Sweego ?????????: composer require symfony/sweego-notifier
DSN: sweego://API_KEY@default?region=REGION&campaign_type=CAMPAIGN_TYPE
????????? ???-?????: Yes
Telnyx ?????????: composer require symfony/telnyx-notifier
DSN: telnyx://API_KEY@default?from=FROM&messaging_profile_id=MESSAGING_PROFILE_ID
????????? ???-?????: ???
TurboSms ?????????: composer require symfony/turbo-sms-notifier
DSN: turbosms://AUTH_TOKEN@default?from=FROM
????????? ???-?????: ???
Twilio ?????????: composer require symfony/twilio-notifier
DSN: twilio://SID:TOKEN@default?from=FROM
????????? ???-?????: ??
Unifonic ?????????: composer require symfony/unifonic-notifier
DSN: unifonic://APP_SID@default?from=FROM
????????? ???-?????: ???
Vonage ?????????: composer require symfony/vonage-notifier
DSN: vonage://KEY:SECRET@default?from=FROM
????????? ???-?????: ??
Yunpian ?????????: composer require symfony/yunpian-notifier
DSN: yunpian://APIKEY@default
????????? ???-?????: ???

Tip

Используйте секреты конфигурации Symfony, чтобы безопасно хранить ваши токены API.

Tip

Некоторые сторонние транспорты, использующие API, поддерживают обратные вызовы статуса через веб-хуки. Подробнее см. в документации документации Webhook.

7.1

Интеграции Smsbox, SmsSluzba, SMSense, LOX24 и Unifonic были представлены в Symfony 7.1.

7.2

Интеграции Primotexto, Sipgate и Sweego были представлены в Symfony 7.2.

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
32
33
// 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',
            // вы также можете добавить объект опций, реализующий MessageOptionsInterface
            $options
        );

        $sentMessage = $texter->send($sms);

        // ...
    }
}

Метод send() возвращает переменную типа SentMessage, которая предоставляет информацию ворде ID сообщения и изначального содержания сообщения.

Чат-канал

Warning

Если любое из значений DSN содержит любой символ, считающийся специальным в URI (такой как : / ? # [ ] @ ! $ & ' ( ) * + , ; =), вы должны зашифровать его. См. 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
GoogleChat symfony/google-chat-notifier googlechat://ACCESS_KEY:ACCESS_TOKEN@default/SPACE?thread_key=THREAD_KEY
LINE Bot symfony/line-bot-notifier linebot://TOKEN@default?receiver=RECEIVER
LINE Notify symfony/line-notify-notifier linenotify://TOKEN@default
LinkedIn 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
Twitter 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 была представлена в Symfony 7.1.

7.2

Интеграция LINE Bot была представлена в Symfony 7.2.

7.2

Интеграция Gitter была удалена в Symfony 7.2, так как этот сервис больше не предоставляет API.

Warning

По умолчанию, если у вас установлен компонентMessenger, уведомления будут отправляться через MessageBus. Если у вас не запущен потребитель сообщений, сообщения никогда не будут отправляться.

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

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'

Пуш-канал

Warning

Если любое из значений 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
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)%'

Десктоп-канал

Десктоп-канал используется для отображения локальных уведомлений рабочего стола на одной и той же
хост-машине с помощью классов Texter. В настоящее время, Symfony интегрирована со следующими поставщиками:

????????? ????? DSN
JoliNotif symfony/joli-notif-notifier jolinotif://default

7.2

Мост JoliNotif был представлен в Symfony 7.2.

Если вы используете Symfony Flex , установка этого пакета
также создаст необходимую переменную окружения и конфигурацию. В противном случае вам необходимо добавить следующее вручную:

  1. Добавьте правильную DSN в вашем файле .env:
1
2
# .env
JOLINOTIF=jolinotif://default
  1. Обновите конфигурацию Notifier, чтобы добавить новый текстовый транспорт:
1
2
3
4
5
# config/packages/notifier.yaml
framework:
    notifier:
        texter_transports:
            jolinotif: '%env(JOLINOTIF)%'

Теперь вы можете отправлять уведомления на ваш рабочий стол следующим образом:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// src/Notifier/SomeService.php
use Symfony\Component\Notifier\Message\DesktopMessage;
use Symfony\Component\Notifier\TexterInterface;
// ...

class SomeService
{
    public function __construct(
        private TexterInterface $texter,
    ) {
    }

    public function notifyNewSubscriber(User $user): void
    {
        $message = new DesktopMessage(
            'New subscription! 🎉',
            sprintf('%s is a new subscriber', $user->getFullName())
        );

        $texter->send($message);
    }
}

Эти уведомления можно настроить больше, и в зависимости от вашей ОС, они могут поддерживать функции вроде пользовательских звуков, иконок и других:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
use Symfony\Component\Notifier\Bridge\JoliNotif\JoliNotifOptions;
// ...

$options = (new JoliNotifOptions())
    ->setIconPath('/path/to/icons/error.png')
    ->setExtraOption('sound', 'sosumi')
    ->setExtraOption('url', 'https://example.com');

$message = new DesktopMessage('Production is down', <<<CONTENT
    ❌ Server prod-1 down
    ❌ Server prod-2 down
    ✅ Network is up
    CONTENT, $options);

$texter->send($message);

Конфигурация для использования резервного транспорта или 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
32
// src/Controller/InvoiceController.php
namespace App\Controller;

use Symfony\Component\HttpFoundation\Response;
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
Получатель по умолчанию, который полезен, когда не нужно иметь информацию о получателе. Например, канал browser использует flashbag сессии текущего request;
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'];
    }
}

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

У каждого канала есть собственный интерфейс уведомлений, который вы можете реализовать для настройки сообщений уведомлений. Например, если вы хотите изменить сообщение на основе сервиса 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
// 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) {
            $this->subject('You\'re invoiced '.strval($this->price).' EUR.');
            $this->emoji("money");
            return ChatMessage::fromNotification($this);
        }

        // Если вы вернёте null, Notifier создаст ChatMessage
        // так как если бы этого метода не было
        return null;
    }
}

Также есть интерфейсы SmsNotificationInterface, EmailNotificationInterface и PushNotificationInterface для изменения сообщений, отправляемых по этим каналам.

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

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

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

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

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

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('Сообщение с темой: %s не было отправлено успешно. Ошибка: %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()'));
});