Дата обновления перевода: 2020-12-25

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

New in version 5.0: Компонент Notifier появился в Symfony 5.0 как экспериментальная возможность.

Установка

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

1
$ composer require symfony/notifier

Каналы: Chatters, Texters, Email and Browser

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

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

Tip

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

SMS канал

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

Сервис Пакет DSN
Esendex symfony/esendex-notifier esendex://USER_NAME:PASSWORD@default?accountreference=ACCOUNT_REFERENCE&from=FROM
FreeMobile symfony/free-mobile-notifier freemobile://LOGIN:PASSWORD@default?phone=PHONE
Infobip symfony/infobip-notifier infobip://TOKEN@default?from=FROM
Mobyt symfony/mobyt-notifier mobyt://USER_KEY:ACCESS_TOKEN@default?from=FROM
Nexmo symfony/nexmo-notifier nexmo://KEY:SECRET@default?from=FROM
OvhCloud symfony/ovhcloud-notifier ovhcloud://APPLICATION_KEY:APPLICATION_SECRET@default?consumer_key=CONSUMER_KEY&service_name=SERVICE_NAME
Sendinblue symfony/sendinblue-notifier sendinblue://API_KEY@default?sender=PHONE
Sinch symfony/sinch-notifier sinch://ACCOUNT_ID:AUTH_TOKEN@default?from=FROM
Smsapi symfony/smsapi-notifier smsapi://TOKEN@default?from=FROM
Twilio symfony/twilio-notifier twilio://SID:TOKEN@default?from=FROM

New in version 5.1: Интеграции OvhCloud, Sinch и FreeMobile появились в Symfony 5.1.

New in version 5.2: Интеграции Smsapi, Infobip, Mobyt, Esendex и Sendinblue появились в Symfony 5.2.

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

1
2
# .env
TWILIO_DSN=twilio://SID:[email protected]?from=FROM
  • YAML
    1
    2
    3
    4
    5
    # config/packages/notifier.yaml
    framework:
        notifier:
            texter_transports:
                twilio: '%env(TWILIO_DSN)%'
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <!-- config/packages/notifier.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:framework="http://symfony.com/schema/dic/symfony"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            https://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/symfony
            https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
    
        <framework:config>
            <framework:notifier>
                <framework:texter-transport name="twilio">
                    %env(TWILIO_DSN)%
                </framework:texter-transport>
            </framework:notifier>
        </framework:config>
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    6
    7
    8
    # config/packages/notifier.php
    $container->loadFromExtension('framework', [
        'notifier' => [
            'texter_transports' => [
                'twilio' => '%env(TWILIO_DSN)%',
            ],
        ],
    ]);
    

Chat канал

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

Service Package DSN
GoogleChat symfony/google-chat-notifier googlechat://ACCESS_KEY:ACCESS_TOKEN@default/SPACE?threadKey=THREAD_KEY
LinkedIn symfony/linked-in-notifier linkedin://TOKEN:USER_ID@default
Mattermost symfony/mattermost-notifier mattermost://TOKEN@ENDPOINT?channel=CHANNEL
RocketChat symfony/rocket-chat-notifier rocketchat://TOKEN@ENDPOINT?channel=CHANNEL
Slack symfony/slack-notifier slack://default/ID
Telegram symfony/telegram-notifier telegram://TOKEN@default?channel=CHAT_ID
Zulip symfony/zulip-notifier zulip://EMAIL:APIKEY@ENDPOINT?channel=CHANNEL

New in version 5.1: Интеграции с Mattermost и RocketChat появились в Symfony 5.1. Slack DSN изменилась в Symfony 5.1 для использования Slack Incoming Webhooks вместо устаревших токенов.

New in version 5.2: Интеграции с GoogleChat, LinkedIn и Zulip появились в Symfony 5.2.

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

1
2
# .env
SLACK_DSN=slack://default/ID
  • YAML
    1
    2
    3
    4
    5
    # config/packages/notifier.yaml
    framework:
        notifier:
            chatter_transports:
                slack: '%env(SLACK_DSN)%'
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <!-- config/packages/notifier.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:framework="http://symfony.com/schema/dic/symfony"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            https://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/symfony
            https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
    
        <framework:config>
            <framework:notifier>
                <framework:chatter-transport name="slack">
                    %env(SLACK_DSN)%
                </framework:chatter-transport>
            </framework:notifier>
        </framework:config>
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    6
    7
    8
    # config/packages/notifier.php
    $container->loadFromExtension('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
    1
    2
    3
    4
    5
    6
    # config/packages/mailer.yaml
    framework:
        mailer:
            dsn: '%env(MAILER_DSN)%'
            envelope:
                sender: '[email protected]'
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <!-- config/packages/mailer.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:framework="http://symfony.com/schema/dic/symfony"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            https://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/symfony
            https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
    
        <framework:config>
            <framework:mailer
                dsn="%env(MAILER_DSN)%"
            >
                <framework:envelope
                    sender="[email protected]"
                />
            </framework:mailer>
        </framework:config>
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    6
    7
    8
    9
    # config/packages/mailer.php
    $container->loadFromExtension('framework', [
        'mailer' => [
            'dsn' => '%env(MAILER_DSN)%',
            'envelope' => [
                'sender' => '[email protected]',
            ],
        ],
    ]);
    

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

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

  • YAML
     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)%'
    
  • XML
     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
    <!-- config/packages/notifier.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:framework="http://symfony.com/schema/dic/symfony"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            https://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/symfony
            https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
    
        <framework:config>
            <framework:notifier>
                <!-- Send notifications to Slack and use Telegram if
                     Slack errored -->
                <framework:chatter-transport name="slack">
                    %env(SLACK_DSN)% || %env(TELEGRAM_DSN)%
                </framework:chatter-transport>
    
                <!-- Send notifications to the next scheduled transport
                     calculated by round robin -->
                <framework:chatter-transport name="slack"><![CDATA[
                    %env(SLACK_DSN)% && %env(TELEGRAM_DSN)%
                ]]></framework:chatter-transport>
            </framework:notifier>
        </framework:config>
    </container>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    # config/packages/notifier.php
    $container->loadFromExtension('framework', [
        'notifier' => [
            'chatter_transports' => [
                // Send notifications to Slack and use Telegram if
                // Slack errored
                'main' => '%env(SLACK_DSN)% || %env(TELEGRAM_DSN)%',
    
                // Send notifications to the next scheduled transport calculated by 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
33
// 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()
        );

        // Отправить уведомление получателю
        $sentMessage = $notifier->send($notification, $recipient);

        // ...
    }
}

Уведомление Notification создаётся с 2 аргументами: тема и каналы. Каналы указывают, какой канал или транспорт должен использоваться для отправки уведомления. Например, ['email', 'sms'] отправят и email и sms-уведомление пользователю.

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

New in version 5.2: Класс SentMessage появился в Symfony 5.2.

Уведомление по умолчаниют также имеет методы content() и emoji() для установки текста и иконки уведомления.

Symfony предоставляет таких получателей:

NoRecipient
Получатель по умолчанию, который полезен, когда не нужно иметь информацию о получателе. Например, канал browser использует flashbag сессии текущего request;
Recipient
Может содержать и email и телефон пользователя. Этот получатель может использоваться для всех каналов (зависит от того установлены ли они действительно).

New in version 5.2: Класс AdminRecipient удалён в Symfony 5.2, используйте вместо него Recipient.

Настройка политик каналов

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

  • YAML
     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']
    
                # Использовать browser для уведомлений уровня средний и низкий
                medium: ['browser']
                low: ['browser']
    
  • XML
     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
    <!-- config/packages/notifier.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:framework="http://symfony.com/schema/dic/symfony"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            https://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/symfony
            https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
    
        <framework:config>
            <framework:notifier>
                <!-- ... -->
    
                <framework:channel-policy>
                    <!-- Use SMS, Slack and Email for urgent notifications -->
                    <framework:urgent>sms</framework:urgent>
                    <framework:urgent>chat/slack</framework:urgent>
                    <framework:urgent>email</framework:urgent>
    
                    <!-- Use Slack for highly important notifications -->
                    <framework:high>chat/slack</framework:high>
    
                    <!-- Use browser for medium and low notifications -->
                    <framework:medium>browser</framework:medium>
                    <framework:low>browser</framework:low>
                </framework:channel-policy>
            </framework:notifier>
        </framework:config>
    </container>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    # config/packages/notifier.php
    $container->loadFromExtension('framework', [
        'notifier' => [
            // ...
            'channel_policy' => [
                // Use SMS, Slack and email for urgent notifications
                'urgent' => ['sms', 'chat/slack', 'email'],
    
                // Use Slack for highly important notifications
                'high' => ['chat/slack'],
    
                // Use browser for medium and low notifications
                'medium' => ['browser'],
                'low' => ['browser'],
            ],
        ],
    ]);
    

Теперь, когда важность уведомления установлена в "high", оно будет отправлено через транспорт Slack:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// ...
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('[email protected]'));

        // ...
    }
}

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

Вы можете расширить базовые классы 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 для изменения сообщений, отправляемых по этим каналам.

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

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

Эта документация является переводом официальной документации Symfony и предоставляется по свободной лицензии CC BY-SA 3.0.