single: Notifier
Current web applications use many different channels to send messages to the users (e.g. SMS, Slack messages, emails, push notifications, etc.). The Notifier component in Symfony is an abstraction on top of all these channels. It provides a dynamic way to manage how the messages are sent. Get the Notifier installed using:
$ composer require symfony/notifier
The notifier component can send notifications to different channels. Each channel can integrate with different providers (e.g. Slack or Twilio SMS) by using transports.
The notifier component supports the following channels:
SMS channel <notifier-sms-channel>
sends notifications to phones via SMS messages;Chat channel <notifier-chat-channel>
sends notifications to chat services like Slack and Telegram;Email channel <notifier-email-channel>
integrates theSymfony Mailer </mailer>
;- Browser channel uses
flash messages <flash-messages>
. Push channel <notifier-push-channel>
sends notifications to phones and browsers via push notifications.
Tip
Use secrets </configuration/secrets>
to securely store your API's tokens.
Caution
If any of the DSN values contains any character considered special in a URI (such as +
, @
, $
, #
, /
, :
, *
, !
), you must encode them. See RFC 3986 for the full list of reserved characters or use the urlencode
function to encode them.
The SMS channel uses Symfony\\Component\\Notifier\\Texter
classes to send SMS messages to mobile phones. This feature requires subscribing to a third-party service that sends SMS messages. Symfony provides integration with a couple popular SMS services:
Service | Package | DSN |
---|---|---|
46elks | symfony/forty-six-elks-notifier |
forty-six-elks://API_USERNAME:API_PASSWORD@default?from=FROM |
AllMySms | symfony/all-my-sms-notifier |
allmysms://LOGIN:APIKEY@default?from=FROM |
AmazonSns | symfony/amazon-sns-notifier |
sns://ACCESS_KEY:SECRET_KEY@default?region=REGION |
Bandwidth | symfony/bandwidth-notifier |
bandwidth://USERNAME:PASSWORD@default?from=FROM&account_id=ACCOUNT_ID&application_id=APPLICATION_ID&priority=PRIORITY |
Clickatell | symfony/clickatell-notifier |
clickatell://ACCESS_TOKEN@default?from=FROM |
ContactEveryone | symfony/contact-everyone-notifier |
contact-everyone://TOKEN@default?&diffusionname=DIFFUSION_NAME&category=CATEGORY |
Esendex | symfony/esendex-notifier |
esendex://USER_NAME:PASSWORD@default?accountreference=ACCOUNT_REFERENCE&from=FROM |
FakeSms | symfony/fake-sms-notifier |
fakesms+email://MAILER_SERVICE_ID?to=TO&from=FROM or fakesms+logger://default |
FreeMobile | symfony/free-mobile-notifier |
freemobile://LOGIN:API_KEY@default?phone=PHONE |
GatewayApi | symfony/gateway-api-notifier |
gatewayapi://TOKEN@default?from=FROM |
Infobip | symfony/infobip-notifier |
infobip://AUTH_TOKEN@HOST?from=FROM |
Iqsms | symfony/iqsms-notifier |
iqsms://LOGIN:PASSWORD@default?from=FROM |
iSendPro | symfony/isendpro-notifier |
isendpro://ACCOUNT_KEY_ID@default?from=FROM&no_stop=NO_STOP&sandbox=SANDBOX |
KazInfoTeh | symfony/kaz-info-teh-notifier |
kaz-info-teh://USERNAME:PASSWORD@default?sender=FROM |
LightSms | symfony/light-sms-notifier |
lightsms://LOGIN:TOKEN@default?from=PHONE |
Mailjet | symfony/mailjet-notifier |
mailjet://TOKEN@default?from=FROM |
MessageBird | symfony/message-bird-notifier |
messagebird://TOKEN@default?from=FROM |
MessageMedia | symfony/message-media-notifier |
messagemedia://API_KEY:API_SECRET@default?from=FROM |
Mobyt | symfony/mobyt-notifier |
mobyt://USER_KEY:ACCESS_TOKEN@default?from=FROM |
Nexmo | symfony/nexmo-notifier |
Abandoned in favor of Vonage (symfony/vonage-notifier). |
Octopush | symfony/octopush-notifier |
octopush://USERLOGIN:APIKEY@default?from=FROM&type=TYPE |
OrangeSms | symfony/orange-sms-notifier |
orange-sms://CLIENT_ID:CLIENT_SECRET@default?from=FROM&sender_name=SENDER_NAME |
OvhCloud | symfony/ovh-cloud-notifier |
ovhcloud://APPLICATION_KEY:APPLICATION_SECRET@default?consumer_key=CONSUMER_KEY&service_name=SERVICE_NAME&no_stop_clause=true |
Plivo | symfony/plivo-notifier |
plivo://AUTH_ID:AUTH_TOKEN@default?from=FROM |
RingCentral | symfony/ring-central-notifier |
ringcentral://API_TOKEN@default?from=FROM |
Sendberry | symfony/sendberry-notifier |
sendberry://USERNAME:PASSWORD@default?auth_key=AUTH_KEY&from=FROM |
Sendinblue | symfony/sendinblue-notifier |
sendinblue://API_KEY@default?sender=PHONE |
Sms77 | symfony/sms77-notifier |
sms77://API_KEY@default?from=FROM |
Sinch | symfony/sinch-notifier |
sinch://ACCOUNT_ID:AUTH_TOKEN@default?from=FROM |
Smsapi | symfony/smsapi-notifier |
smsapi://TOKEN@default?from=FROM&test=0 |
SmsBiuras | symfony/sms-biuras-notifier |
smsbiuras://UID:API_KEY@default?from=FROM&test_mode=0 |
Smsc | symfony/smsc-notifier |
smsc://LOGIN:PASSWORD@default?from=FROM |
SMSFactor | symfony/sms-factor-notifier |
sms-factor://TOKEN@default?sender=SENDER&push_type=PUSH_TYPE |
SpotHit | symfony/spot-hit-notifier |
spothit://TOKEN@default?from=FROM |
Telnyx | symfony/telnyx-notifier |
telnyx://API_KEY@default?from=FROM&messaging_profile_id=MESSAGING_PROFILE_ID |
Termii | symfony/termii-notifier |
termii://API_KEY@default?from=FROM&channel=CHANNEL |
TurboSms | symfony/turbo-sms-notifier |
turbosms://AUTH_TOKEN@default?from=FROM |
Twilio | symfony/twilio-notifier |
twilio://SID:TOKEN@default?from=FROM |
Vonage | symfony/vonage-notifier |
vonage://KEY:SECRET@default?from=FROM |
Yunpian | symfony/yunpian-notifier |
yunpian://APIKEY@default |
6.1
The 46elks, OrangeSms, KazInfoTeh and Sendberry integrations were introduced in Symfony 6.1. The no_stop_clause
option in OvhCloud
DSN was introduced in Symfony 6.1. The test
option in Smsapi
DSN was introduced in Symfony 6.1.
6.2
The ContactEveryone and SMSFactor integrations were introduced in Symfony 6.2.
6.3
The Bandwith, iSendPro, Plivo, RingCentral and Termii integrations were introduced in Symfony 6.3. The from
option in Smsapi
DSN is optional since Symfony 6.3.
To enable a texter, add the correct DSN in your .env
file and configure the texter_transports
:
# .env
TWILIO_DSN=twilio://SID:TOKEN@default?from=FROM
# config/packages/notifier.yaml
framework:
notifier:
texter_transports:
twilio: '%env(TWILIO_DSN)%'
<!-- 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>
// config/packages/notifier.php
use Symfony\Config\FrameworkConfig;
return static function (FrameworkConfig $framework) {
$framework->notifier()
->texterTransport('twilio', env('TWILIO_DSN'))
;
};
The Symfony\\Component\\Notifier\\TexterInterface
class allows you to send SMS messages:
// src/Controller/SecurityController.php
namespace App\Controller;
use Symfony\Component\Notifier\Message\SmsMessage;
use Symfony\Component\Notifier\TexterInterface;
use Symfony\Component\Routing\Annotation\Route;
class SecurityController
{
#[Route('/login/success')]
public function loginSuccess(TexterInterface $texter)
{
$sms = new SmsMessage(
// the phone number to send the SMS message to
'+1411111111',
// the message
'A new login was detected!',
// optionally, you can override default "from" defined in transports
'+1422222222',
);
$sentMessage = $texter->send($sms);
// ...
}
}
6.2
The 3rd argument of SmsMessage
($from
) was introduced in Symfony 6.2.
The send()
method returns a variable of type Symfony\\Component\\Notifier\\Message\\SentMessage
which provides information such as the message ID and the original message contents.
Caution
If any of the DSN values contains any character considered special in a URI (such as +
, @
, $
, #
, /
, :
, *
, !
), you must encode them. See RFC 3986 for the full list of reserved characters or use the urlencode
function to encode them.
The chat channel is used to send chat messages to users by using Symfony\\Component\\Notifier\\Chatter
classes. Symfony provides integration with these chat services:
Service | Package | 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 <notifier/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 |
|
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 <notifier/teams> |
symfony/microsoft-teams-notifier |
microsoftteams://default/PATH |
RocketChat | symfony/rocket-chat-notifier |
rocketchat://TOKEN@ENDPOINT?channel=CHANNEL |
Slack <notifier/slack> |
symfony/slack-notifier |
slack://TOKEN@default?channel=CHANNEL |
Telegram <notifier/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 |
6.2
The Zendesk and Chatwork integration were introduced in Symfony 6.2.
6.3
The LINE Notify, Mastodon and Twitter integrations were introduced in Symfony 6.3.
Chatters are configured using the chatter_transports
setting:
# .env
SLACK_DSN=slack://TOKEN@default?channel=CHANNEL
# config/packages/notifier.yaml
framework:
notifier:
chatter_transports:
slack: '%env(SLACK_DSN)%'
<!-- 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>
// config/packages/notifier.php
use Symfony\Config\FrameworkConfig;
return static function (FrameworkConfig $framework) {
$framework->notifier()
->chatterTransport('slack', env('SLACK_DSN'))
;
};
The Symfony\\Component\\Notifier\\ChatterInterface
class allows you to send messages to chat services:
// src/Controller/CheckoutController.php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Notifier\ChatterInterface;
use Symfony\Component\Notifier\Message\ChatMessage;
use Symfony\Component\Routing\Annotation\Route;
class CheckoutController extends AbstractController
{
/**
* @Route("/checkout/thankyou")
*/
public function thankyou(ChatterInterface $chatter)
{
$message = (new ChatMessage('You got a new invoice for 15 EUR.'))
// if not set explicitly, the message is sent to the
// default transport (the first one configured)
->transport('slack');
$sentMessage = $chatter->send($message);
// ...
}
}
The send()
method returns a variable of type Symfony\\Component\\Notifier\\Message\\SentMessage
which provides information such as the message ID and the original message contents.
The email channel uses the Symfony Mailer </mailer>
to send notifications using the special Symfony\\Bridge\\Twig\\Mime\\NotificationEmail
. It is required to install the Twig bridge along with the Inky and CSS Inliner Twig extensions:
$ composer require symfony/twig-pack twig/cssinliner-extra twig/inky-extra
After this, configure the mailer <mailer-transport-setup>
. You can also set the default "from" email address that should be used to send the notification emails:
# config/packages/mailer.yaml
framework:
mailer:
dsn: '%env(MAILER_DSN)%'
envelope:
sender: 'notifications@example.com'
<!-- 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="notifications@example.com"
/>
</framework:mailer>
</framework:config>
</container>
// config/packages/mailer.php
use Symfony\Config\FrameworkConfig;
return static function (FrameworkConfig $framework) {
$framework->mailer()
->dsn(env('MAILER_DSN'))
->envelope()
->sender('notifications@example.com')
;
};
Caution
If any of the DSN values contains any character considered special in a URI (such as +
, @
, $
, #
, /
, :
, *
, !
), you must encode them. See RFC 3986 for the full list of reserved characters or use the urlencode
function to encode them.
The push channel is used to send notifications to users by using Symfony\\Component\\Notifier\\Texter
classes. Symfony provides integration with these push services:
Service | Package | DSN |
---|---|---|
Engagespot | symfony/engagespot-notifier |
|
Expo | symfony/expo-notifier |
|
OneSignal | symfony/one-signal-notifier |
|
PagerDuty | symfony/pager-duty-notifier |
|
Pushover | symfony/pushover-notifier |
|
6.1
The Engagespot integration was introduced in Symfony 6.1.
6.3
The PagerDuty and Pushover integrations were introduced in Symfony 6.3.
To enable a texter, add the correct DSN in your .env
file and configure the texter_transports
:
# .env
EXPO_DSN=expo://TOKEN@default
# config/packages/notifier.yaml
framework:
notifier:
texter_transports:
expo: '%env(EXPO_DSN)%'
<!-- 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="expo">
%env(EXPO_DSN)%
</framework:texter-transport>
</framework:notifier>
</framework:config>
</container>
// config/packages/notifier.php
use Symfony\Config\FrameworkConfig;
return static function (FrameworkConfig $framework) {
$framework->notifier()
->texterTransport('expo', env('EXPO_DSN'))
;
};
Besides configuring one or more separate transports, you can also use the special ||
and &&
characters to implement a failover or round-robin transport:
# config/packages/notifier.yaml
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)%'
<!-- 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>
// config/packages/notifier.php
use Symfony\Config\FrameworkConfig;
return static function (FrameworkConfig $framework) {
$framework->notifier()
// Send notifications to Slack and use Telegram if
// Slack errored
->chatterTransport('main', env('SLACK_DSN').' || '.env('TELEGRAM_DSN'))
// Send notifications to the next scheduled transport calculated by round robin
->chatterTransport('roundrobin', env('SLACK_DSN').' && '.env('TELEGRAM_DSN'))
;
};
To send a notification, autowire the Symfony\\Component\\Notifier\\NotifierInterface
(service ID notifier
). This class has a send()
method that allows you to send a Symfony\\Component\\Notifier\\Notification\\Notification
to a Symfony\\Component\\Notifier\\Recipient\\Recipient
:
// 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)
{
// ...
// Create a Notification that has to be sent
// using the "email" channel
$notification = (new Notification('New Invoice', ['email']))
->content('You got a new invoice for 15 EUR.');
// The receiver of the Notification
$recipient = new Recipient(
$user->getEmail(),
$user->getPhonenumber()
);
// Send the notification to the recipient
$notifier->send($notification, $recipient);
// ...
}
}
The Notification
is created by using two arguments: the subject and channels. The channels specify which channel (or transport) should be used to send the notification. For instance, ['email', 'sms']
will send both an email and sms notification to the user.
The default notification also has a content()
and emoji()
method to set the notification content and icon.
Symfony provides the following recipients:
Symfony\\Component\\Notifier\\Recipient\\NoRecipient
This is the default and is useful when there is no need to have information about the receiver. For example, the browser channel uses the current requests'
session flashbag <flash-messages>
;Symfony\\Component\\Notifier\\Recipient\\Recipient
This can contain both the email address and the phone number of the user. This recipient can be used for all channels (depending on whether they are actually set).
Instead of specifying the target channels on creation, Symfony also allows you to use notification importance levels. Update the configuration to specify what channels should be used for specific levels (using channel_policy
):
# config/packages/notifier.yaml
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']
<!-- 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>
// config/packages/notifier.php
use Symfony\Config\FrameworkConfig;
return static function (FrameworkConfig $framework) {
// ...
$framework->notifier()
// Use SMS, Slack and email for urgent notifications
->channelPolicy('urgent', ['sms', 'chat/slack', 'email'])
// Use Slack for highly important notifications
->channelPolicy('high', ['chat/slack'])
// Use browser for medium and low notifications
->channelPolicy('medium', ['browser'])
->channelPolicy('low', ['browser'])
;
};
Now, whenever the notification's importance is set to "high", it will be sent using the Slack transport:
// ...
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'));
// ...
}
}
You can extend the Notification
or Recipient
base classes to customize their behavior. For instance, you can overwrite the getChannels()
method to only return sms
if the invoice price is very high and the recipient has a phone number:
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)
{
if (
$this->price > 10000
&& $recipient instanceof SmsRecipientInterface
) {
return ['sms'];
}
return ['email'];
}
}
Each channel has its own notification interface that you can implement to customize the notification message. For instance, if you want to modify the message based on the chat service, implement Symfony\\Component\\Notifier\\Notification\\ChatNotificationInterface
and its asChatMessage()
method:
// 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
{
// Add a custom subject and emoji if the message is sent to Slack
if ('slack' === $transport) {
$this->subject('You\'re invoiced '.strval($this->price).' EUR.');
$this->emoji("money");
return ChatMessage::fromNotification($this);
}
// If you return null, the Notifier will create the ChatMessage
// based on this notification as it would without this method.
return null;
}
}
The Symfony\\Component\\Notifier\\Notification\\SmsNotificationInterface
, Symfony\\Component\\Notifier\\Notification\\EmailNotificationInterface
and Symfony\\Component\\Notifier\\Notification\\PushNotificationInterface
also exists to modify messages sent to those channels.
6.1
Support for customizing importance levels was introduced in Symfony 6.1.
The default behavior for browser channel notifications is to add a flash message <flash-messages>
with notification
as its key.
However, you might prefer to map the importance level of the notification to the type of flash message, so you can tweak their style.
you can do that by overriding the default notifier.flash_message_importance_mapper
service with your own implementation of Symfony\\Component\\Notifier\\FlashMessage\\FlashMessageImportanceMapperInterface
where you can provide your own "importance" to "alert level" mapping.
Symfony currently provides an implementation for the Bootstrap CSS framework's typical alert levels, which you can implement immediately using:
# config/services.yaml
services:
notifier.flash_message_importance_mapper:
class: Symfony\Component\Notifier\FlashMessage\BootstrapFlashMessageImportanceMapper
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
https://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="notifier.flash_message_importance_mapper" class="Symfony\Component\Notifier\FlashMessage\BootstrapFlashMessageImportanceMapper"/>
</services>
</container>
// config/services.php
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
use Symfony\Component\Notifier\FlashMessage\BootstrapFlashMessageImportanceMapper;
return function(ContainerConfigurator $containerConfigurator) {
$containerConfigurator->services()
->set('notifier.flash_message_importance_mapper', BootstrapFlashMessageImportanceMapper::class)
;
};
Symfony provides a Symfony\\Bundle\\FrameworkBundle\\Test\\NotificationAssertionsTrait
which provide useful methods for testing your Notifier implementation. You can benefit from this class by using it directly or extending the Symfony\\Bundle\\FrameworkBundle\\Test\\KernelTestCase
.
See testing documentation <notifier-assertions>
for the list of available assertions.
6.2
The Symfony\\Bundle\\FrameworkBundle\\Test\\NotificationAssertionsTrait
was introduced in Symfony 6.2.
While developing (or testing), you may want to disable delivery of notifications entirely. You can do this by forcing Notifier to use the NullTransport
for all configured texter and chatter transports only in the dev
(and/or test
) environment:
# config/packages/dev/notifier.yaml
framework:
notifier:
texter_transports:
twilio: 'null://null'
chatter_transports:
slack: 'null://null'
single: Notifier; Events
The Symfony\\Component\\Notifier\\Transport
` class of the Notifier component allows you to optionally hook into the lifecycle via events.
Typical Purposes: Doing something before the message is send (like logging which message is going to be send, or displaying something about the event to be executed.
Just before send the message, the event class MessageEvent
is dispatched. Listeners receive a Symfony\\Component\\Notifier\\Event\\MessageEvent
event:
use Symfony\Component\Notifier\Event\MessageEvent;
$dispatcher->addListener(MessageEvent::class, function (MessageEvent $event) {
// gets the message instance
$message = $event->getMessage();
// log something
$this->logger(sprintf('Message with subject: %s will be send to %s, $message->getSubject(), $message->getRecipientId()'));
});
Typical Purposes: Doing something before the exception is thrown (Retry to send the message or log additional information).
Whenever an exception is thrown while sending the message, the event class FailedMessageEvent
is dispatched. A listener can do anything useful before the exception is thrown.
Listeners receive a Symfony\\Component\\Notifier\\Event\\FailedMessageEvent
event:
use Symfony\Component\Notifier\Event\FailedMessageEvent;
$dispatcher->addListener(FailedMessageEvent::class, function (FailedMessageEvent $event) {
// gets the message instance
$message = $event->getMessage();
// gets the error instance
$error = $event->getError();
// log something
$this->logger(sprintf('The message with subject: %s has not been sent successfully. The error is: %s, $message->getSubject(), $error->getMessage()'));
});
Typical Purposes: To perform some action when the message is successfully sent (like retrieve the id returned when the message is sent).
After the message has been successfully sent, the event class SentMessageEvent
is dispatched. Listeners receive a Symfony\\Component\\Notifier\\Event\\SentMessageEvent
event:
use Symfony\Component\Notifier\Event\SentMessageEvent;
$dispatcher->addListener(SentMessageEvent::class, function (SentMessageEvent $event) {
// gets the message instance
$message = $event->getOriginalMessage();
// log something
$this->logger(sprintf('The message has been successfully sent and has id: %s, $message->getMessageId()'));
});