SF
{ }
Symfony · Notifier · Slack · Teams · SMS
Symfony Notifier: Slack, Teams
und SMS mit einem Interface

In den meisten Anwendungen gibt es drei, vier verschiedene Bibliotheken für Benachrichtigungen: eine für E-Mails, eine für Slack, eine für SMS, eine für Push-Notifications. Symfony Notifier vereint alle Kanäle hinter einem einzigen Interface und einer einzigen Dispatch-Methode — mit konfigurierbarem Routing, kanalspezifischen Nachrichten und der Möglichkeit, eigene Bridges für interne Systeme zu schreiben.

16 Min. Lesezeit Channels · Chatter · Texter · Bridges · Routing Symfony 7.x · PHP 8.3+ · Slack · Teams · Twilio

1. Warum Symfony Notifier statt einzelner Bibliotheken?

Symfony Notifier löst ein Organisations- und Wartbarkeitsproblem: Jede Benachrichtigungsintegration, die separat implementiert wird, bringt eigene Konfiguration, eigene Fehlerbehandlung und eigene Abstraktion mit. Das bedeutet vier verschiedene API-Clients, vier verschiedene Konfigurationsblöcke und vier verschiedene Teststrategien für Slack, Teams, SMS und E-Mail. Mit Symfony Notifier gibt es einen einzigen NotifierInterface, der eine Notification entgegennimmt und sie — basierend auf der Konfiguration — an einen oder mehrere Kanäle weiterleitet. Das vereinheitlicht nicht nur den Code, sondern auch das Testen und das Monitoring.

Der zweite Vorteil ist das deklarative Routing. Statt im Code zu entscheiden, ob eine Nachricht an Slack oder Teams geht, definiert man in der Konfiguration: "Kritische Fehler gehen an den Chat-Kanal, SMS-Kanal und E-Mail-Kanal gleichzeitig. Marketing-Events gehen nur an Slack." Die Notification-Klasse trägt die Dringlichkeit, das Routing bestimmt die Kanäle. Das ermöglicht es, Routing-Entscheidungen zu ändern, ohne Code anzufassen. Symfony Notifier unterstützt über 80 offizielle Bridges für externe Dienste — von Twilio und Vonage für SMS bis zu PagerDuty und OpsGenie für Incident-Management.

2. Architektur: Channels, Chatter, Texter und Browser

Die Symfony Notifier-Architektur ist in Channels aufgeteilt, die jeweils bestimmte Kommunikationsarten kapseln. Der Chat-Channel verwaltet Messaging-Dienste wie Slack, Microsoft Teams, Telegram und Discord — alles, was eine asynchrone Team-Kommunikationsplattform ist. Der SMS-Channel verwaltet Textnachrichten über Telekommunikationsanbieter wie Twilio, Vonage und Sinch. Der Email-Channel integriert Symfony Mailer — eine Notification, die den Email-Channel nutzt, wird als E-Mail über den konfigurierten Mailer-Transport gesendet. Der Browser-Channel erzeugt Flash-Messages in der Symfony-Session für sofortige Benutzer-Feedback im Browser.

Die Klassen ChatterInterface und TexterInterface sind spezialisierte Versionen für Chat und SMS, wenn man direkt einen spezifischen Transport ansprechen will. Der NotifierInterface ist das übergeordnete Interface, das alle Channels koordiniert: Es empfängt eine Notification, prüft deren Wichtigkeitsstufe (Urgency), und routet sie an alle relevanten Channels. Dieses Routing geschieht entweder automatisch basierend auf Konfiguration oder explizit durch das Setzen des Empfängers (Recipient) in der Notification. Ein Recipient hat eine E-Mail-Adresse und optional eine Telefonnummer — Symfony Notifier nutzt diese, um zu entscheiden, welche Channels sinnvoll sind.


<?php

declare(strict_types=1);

namespace App\Notification;

use Symfony\Component\Notifier\Notification\Notification;
use Symfony\Component\Notifier\Recipient\Recipient;

// Basic notification — subject, content, importance level, channels
final class OrderFailedNotification extends Notification
{
    public function __construct(
        private readonly int $orderId,
        private readonly string $errorMessage,
    ) {
        parent::__construct(
            subject: sprintf('Order #%d processing failed', $this->orderId),
        );
    }

    /**
     * Define urgency and channels — channels filter which transports handle this notification.
     */
    public function getChannels(Recipient $recipient): array
    {
        // URGENT: send via chat (Slack), SMS and email simultaneously
        if ($this->getImportance() === Notification::IMPORTANCE_URGENT) {
            return ['chat/slack', 'sms', 'email'];
        }

        // HIGH: chat and email only
        return ['chat/slack', 'email'];
    }

    /**
     * Build the Slack message — channel-specific content via ChatNotificationInterface.
     */
    public function asChatMessage(
        \Symfony\Component\Notifier\Recipient\RecipientInterface $recipient,
        string $transport = null,
    ): ?\Symfony\Component\Notifier\Message\ChatMessage {
        if ($transport !== 'slack') {
            return null; // Let the parent class handle other chat transports
        }

        $message = new \Symfony\Component\Notifier\Message\ChatMessage(
            subject: $this->getSubject(),
        );

        // Attach Slack-specific Block Kit options
        $message->options(
            (new \Symfony\Component\Notifier\Bridge\Slack\SlackOptions())
                ->iconEmoji('warning')
                ->block((new \Symfony\Component\Notifier\Bridge\Slack\Block\SlackSectionBlock())
                    ->text(sprintf("*Order #%d failed*\n%s", $this->orderId, $this->errorMessage))
                )
        );

        return $message;
    }
}

3. Installation und erste Notification versenden

Die Installation von Symfony Notifier erfolgt modular: Das Basis-Paket symfony/notifier enthält das Interface und den Core. Für jeden Kanal installiert man das entsprechende Bridge-Paket — symfony/slack-notifier für Slack, symfony/microsoft-teams-notifier für Teams, symfony/twilio-notifier für SMS via Twilio. Symfony Flex installiert nicht nur das Paket, sondern legt auch die entsprechende Konfiguration in config/packages/notifier.yaml an und fügt die DSN-Umgebungsvariablen als Kommentar in .env ein.

Eine Notification zu versenden ist in Symfony Notifier eine Frage von drei Zeilen: Notification erstellen, Recipient mit E-Mail und Telefonnummer erstellen, NotifierInterface::send() aufrufen. Der Notifier prüft die konfigurierten Channels, bestimmt anhand der Recipient-Daten und der Notification-Kanäle, wohin die Nachricht geht, und delegiert an die entsprechenden Transports. Das Versenden ist standardmäßig synchron — für asynchrones Versenden über Symfony Messenger konfiguriert man den messenger-Transport in der Notifier-Konfiguration, und die Notifications werden automatisch in eine Queue gestellt.

4. Slack-Nachrichten mit Block-Kit und Attachments

Slack-Nachrichten in Symfony Notifier können über den SlackOptions-Block-Builder mit dem vollen Slack Block Kit formatiert werden. Das Block Kit erlaubt strukturierte Nachrichten mit Abschnitten, Buttons, Dropdown-Menüs, Bildern und Trennlinien — weit über einfachen Text hinaus. Eine Deployment-Benachrichtigung kann einen Header mit dem Deploy-Status, einen Abschnitt mit Branches und Commit-Hash, ein Kontext-Block mit Zeitstempel und Deployer und einen Action-Block mit "Rollback"-Button enthalten. All das wird über den PHP-Builder API von SlackOptions aufgebaut, ohne JSON manuell zu schreiben.

Für Incident-Management-Szenarien ist die Kombination von Symfony Notifier mit Slack besonders wertvoll: Ein kritischer Fehler in der Anwendung dispatcht eine Symfony Messenger-Message, die asynchron verarbeitet wird und über den Slack-Kanal eine formatierte Alerting-Nachricht sendet. Der Alert enthält den Fehlerkontext, den Stack-Trace-Link und einen Button, der das Ticket im Issue-Tracker direkt öffnet. Diese Automatisierung ersetzt manuelle Slack-Nachrichten beim On-Call-Dienst und verkürzt die Zeit von Fehler zu erster Reaktion erheblich. Symfony Notifier macht das möglich, ohne einen separaten Alerting-Dienst zu betreiben.


<?php

declare(strict_types=1);

namespace App\Notification;

use Symfony\Component\Notifier\Bridge\Slack\Block\SlackActionsBlock;
use Symfony\Component\Notifier\Bridge\Slack\Block\SlackContextBlock;
use Symfony\Component\Notifier\Bridge\Slack\Block\SlackDividerBlock;
use Symfony\Component\Notifier\Bridge\Slack\Block\SlackHeaderBlock;
use Symfony\Component\Notifier\Bridge\Slack\Block\SlackSectionBlock;
use Symfony\Component\Notifier\Bridge\Slack\SlackOptions;
use Symfony\Component\Notifier\Message\ChatMessage;
use Symfony\Component\Notifier\Recipient\RecipientInterface;

/**
 * Sends a richly formatted Slack deployment notification with Block Kit.
 */
final class DeploymentSlackNotification extends \Symfony\Component\Notifier\Notification\Notification
{
    public function __construct(
        private readonly string $environment,
        private readonly string $version,
        private readonly string $deployer,
        private readonly bool $success,
    ) {
        parent::__construct(subject: sprintf('Deployment %s: %s v%s', $success ? 'successful' : 'FAILED', $environment, $version));
    }

    /**
     * Build a rich Slack Block Kit message for the deployment notification.
     */
    public function asChatMessage(RecipientInterface $recipient, string $transport = null): ?ChatMessage
    {
        $statusEmoji = $this->success ? ':white_check_mark:' : ':rotating_light:';
        $statusText  = $this->success ? 'Deployment successful' : 'Deployment FAILED';

        $options = (new SlackOptions())
            ->iconEmoji($this->success ? 'rocket' : 'fire')
            ->block(new SlackHeaderBlock(sprintf('%s %s', $statusEmoji, $statusText)))
            ->block(
                (new SlackSectionBlock())
                    ->field('*Environment*', $this->environment)
                    ->field('*Version*', $this->version)
            )
            ->block(new SlackDividerBlock())
            ->block(
                (new SlackContextBlock())
                    ->add(sprintf('Deployed by *%s* at %s', $this->deployer, (new \DateTimeImmutable())->format('H:i d.m.Y')))
            );

        // Add action button only for failed deployments
        if (!$this->success) {
            $options->block(
                (new SlackActionsBlock())
                    ->button('Open Runbook', 'https://wiki.example.com/runbook/deploy-failure', 'danger')
            );
        }

        $message = new ChatMessage(subject: $this->getSubject());
        $message->options($options);

        return $message;
    }
}

5. Microsoft Teams: Adaptive Cards versenden

Microsoft Teams-Benachrichtigungen über Symfony Notifier verwenden Adaptive Cards — das offizielle JSON-Format für interaktive Teams-Nachrichten. Der MicrosoftTeamsOptions-Builder erlaubt es, Adaptive Cards deklarativ in PHP aufzubauen: Texte, Tabellen, Fakten-Listen und Action-Buttons werden als PHP-Objekte zusammengesetzt und von der Bridge automatisch in das korrekte Adaptive-Card-JSON-Format konvertiert. Teams-Benachrichtigungen über Incoming Webhooks sind für einfache Szenarien ausreichend — für komplexere Interaktionen mit Bot-Framework und persönlichen Nachrichten an einzelne Benutzer braucht man die Microsoft Graph API, die nicht über den Standard-Notifier abgedeckt wird.

Ein typischer Anwendungsfall für Teams-Benachrichtigungen in Unternehmensumgebungen ist das Monitoring von Geschäftsprozessen: Eine Bestellung über einem bestimmten Warenkorbwert, eine neue Enterprise-Registrierung oder ein abgeschlossenes kritisches Support-Ticket lösen eine Teams-Benachrichtigung an den zuständigen Account-Manager aus. Symfony Notifier routet diese Notifications basierend auf Urgency und Recipient automatisch in den konfigurierten Teams-Kanal. Im Vergleich zu Slack ist Teams vor allem in Microsoft-orientierten Unternehmen die präferierte Plattform — und mit der Teams-Bridge von Symfony Notifier ist der Wechsel von Slack zu Teams oder das parallele Betreiben beider Plattformen eine Konfigurationsänderung ohne Code-Anpassung.

6. SMS mit Twilio, Vonage und anderen Bridges

SMS-Benachrichtigungen in Symfony Notifier gehen über den SMS-Channel und nutzen Bridge-Pakete für externe Telekommunikationsanbieter. Twilio ist der am häufigsten eingesetzte Anbieter und bietet mit dem TwilioTransport zuverlässige Zustellung weltweit. Vonage (früher Nexmo) ist eine Alternative mit starker Präsenz in Europa. Amazon SNS, Sinch, MessageBird und Infobip sind weitere verfügbare Bridges. Die Konfiguration aller SMS-Bridges läuft über eine DSN-Umgebungsvariable: TWILIO_DSN=twilio://SID:TOKEN@default?from=+4912345678. Das Wechseln des SMS-Anbieters ist damit eine Konfigurationsänderung in einer Zeile.

Eine häufige Frage bei Symfony Notifier und SMS ist die Behandlung von Zustellungsberichten. Twilio und Vonage erlauben die Konfiguration von Webhook-Callbacks, wenn eine SMS zugestellt wurde oder fehlgeschlagen ist. Symfony Notifier selbst verwaltet keine Zustellungsberichte — diese kommen als eingehende Webhooks an und werden von Symfony-Controllern verarbeitet, die den Zustellungsstatus in der Anwendungsdatenbank aktualisieren. Das Notifier-Package kümmert sich um das Senden, die Verarbeitung der Callbacks ist anwendungsspezifische Logik. Bei kritischen SMS-Benachrichtigungen — Zwei-Faktor-Authentifizierung, Sicherheitsalarme — empfiehlt sich der symfony/messenger-Transport für asynchrones Versenden mit automatischem Retry bei Fehlern.

7. Routing: welcher Kanal für welche Notification?

Das Routing in Symfony Notifier bestimmt, welche Notification über welche Channels versendet wird. Es gibt zwei Routing-Ebenen: Die erste ist die Konfiguration in notifier.yaml, die Importance-Levels auf Channels mappt. Notifications mit IMPORTANCE_URGENT gehen an Chat und SMS, Notifications mit IMPORTANCE_LOW nur an E-Mail. Die zweite Ebene ist die getChannels()-Methode in der Notification-Klasse, die für jede Notification spezifisch festlegen kann, welche Channels genutzt werden — unabhängig von der globalen Konfiguration.

Für produktive Setups empfiehlt sich eine klare Kanal-Hierarchie: Monitoring-Alerts und kritische Fehler gehen an Slack oder Teams (schnelle Sichtbarkeit), direkte Nutzermitteilungen gehen als SMS (sofortige Aufmerksamkeit), Zusammenfassungen und Reports gehen als E-Mail (persistenter Nachweis). Symfony Notifier unterstützt das parallele Versenden an mehrere Kanäle in einer einzigen Dispatch-Operation — die Notification wird an alle konfigurierten Kanäle gleichzeitig gesendet, nicht sequenziell. Beim asynchronen Versenden über Symfony Messenger wird jeder Kanal als separate Message in die Queue gestellt, was bei Fehlern einzelne Kanäle separat wiederholen lässt.


# config/packages/notifier.yaml
# Symfony Notifier: channel routing and transport configuration

framework:
  notifier:
    # Chat transports — Slack and Teams with Incoming Webhook URLs
    chatter_transports:
      slack:  '%env(SLACK_DSN)%'        # slack://xoxb-TOKEN@default?channel=alerts
      teams:  '%env(TEAMS_DSN)%'        # microsoftteams://default/WEBHOOK_URL

    # SMS transports — Twilio as primary, Vonage as fallback
    texter_transports:
      twilio: '%env(TWILIO_DSN)%'       # twilio://SID:TOKEN@default?from=+49...
      vonage: '%env(VONAGE_DSN)%'       # vonage://KEY:SECRET@default?from=Mironsoft

    # Email channel uses Symfony Mailer — no separate DSN needed
    # Browser channel adds Flash messages to the session

    # Global routing by urgency level
    channel_policy:
      urgent: ['chat/slack', 'sms/twilio', 'email']
      high:   ['chat/slack', 'email']
      medium: ['email']
      low:    ['email']

    # Use Symfony Messenger for async sending — prevents slow HTTP calls in requests
    # messenger_bus: messenger.default_bus

8. Eigene Notifier-Bridge für interne Systeme schreiben

Wenn das interne Monitoring-System, das Issue-Tracking-Tool oder ein Self-hosted Chat-Server keine offizielle Symfony Notifier-Bridge haben, schreibt man eine eigene. Eine Notifier-Bridge besteht aus drei Klassen: dem Transport, der die HTTP-Anfrage an den externen Dienst sendet, dem TransportFactory, der aus dem DSN-String das Transport-Objekt erzeugt, und optional einem Options-Objekt für kanalspezifische Nachrichtenformate. Der Transport implementiert TransportInterface mit einer send()-Methode und einem supports()-Prädikat, das bestimmt, für welche Message-Typen der Transport zuständig ist.

Das DSN-Pattern ist bei eigenen Bridges dasselbe wie bei offiziellen: eigenes-system://TOKEN@host/channel. Der TransportFactory parst diesen String und erzeugt das Transport-Objekt mit den extrahierten Credentials. Die Bridge-Klasse registriert sich über eine Tagged-Service-Konfiguration im DI-Container als bekannter Transport. Nach der Registrierung funktioniert die eigene Bridge identisch wie eine offizielle: Sie erscheint in der notifier.yaml-Konfiguration, wird über den NotifierInterface angesteuert und unterstützt Retry bei Fehlern über den Messenger-Transport. Eigene Bridges zu schreiben ist eine hervorragende Möglichkeit, interne Werkzeuge in das Symfony Notifier-Ökosystem zu integrieren, ohne auf offizielle Unterstützung zu warten.

9. Notifier-Channels im Vergleich

Jeder Symfony Notifier-Channel hat seine eigene Stärke — die Wahl des richtigen Kanals für den richtigen Anwendungsfall ist entscheidend für die Akzeptanz und Wirksamkeit von Benachrichtigungen.

Channel Stärken Einschränkungen Typischer Einsatz
Chat (Slack/Teams) Sofortige Sichtbarkeit, Rich-Text, Buttons Nur Team-intern sichtbar Monitoring-Alerts, Deployments
SMS Höchste Öffnungsrate, kein Internet nötig Kosten pro Nachricht, kein HTML 2FA, kritische Alerts, On-Call
Email HTML, Anhänge, persistenter Nachweis Niedrige Öffnungsrate, langsamer Berichte, Bestätigungen, Rechnungen
Browser (Flash) Sofort für aktuellen User sichtbar Nur für Session-Benutzer Formular-Feedback, Statusmeldungen
Push (Firebase) Auch bei geschlossener App zugestellt Opt-in, plattformabhängig Mobile Apps, Service-Updates

In der Praxis ist die Kombination aus Chat und E-Mail für die meisten Backend-Anwendungen ausreichend: Chat für sofortige Team-Sichtbarkeit bei Fehlern und Deployments, E-Mail für Nutzer-Benachrichtigungen und persistente Protokolle. SMS lohnt sich bei sicherheitskritischen Szenarien (2FA, Sicherheitswarnungen) oder On-Call-Situationen, in denen Chat-Benachrichtigungen übersehen werden könnten. Symfony Notifier macht es trivial, alle drei Kanäle parallel zu nutzen, ohne separaten Code für jeden.

Mironsoft

Symfony Notifier, Alerting-Systeme und Multi-Channel-Benachrichtigungen

Benachrichtigungssystem mit Symfony Notifier aufbauen?

Wir implementieren Multi-Channel-Benachrichtigungssysteme mit Symfony Notifier — von Slack- und Teams-Integration über SMS-Versand bis zu eigenen Bridges für interne Systeme.

Channel-Integration

Slack Block-Kit, Teams Adaptive Cards, SMS-Bridges und E-Mail-Templates für strukturierte Benachrichtigungen

Eigene Bridges

Custom Notifier-Bridges für interne Monitoring-Systeme, Issue-Tracker und Self-hosted Chat-Plattformen

Async-Versand

Symfony Messenger Integration für asynchronen Versand mit Retry-Logik und Failure-Queue

10. Zusammenfassung

Symfony Notifier vereint alle Benachrichtigungskanäle hinter einem einzigen NotifierInterface und eliminiert damit die Notwendigkeit, für jeden Kanal eine separate Integration zu pflegen. Slack Block-Kit, Microsoft Teams Adaptive Cards, SMS über Twilio oder Vonage und Browser Flash-Messages laufen über denselben Dispatch-Mechanismus. Das konfigurative Routing nach Urgency-Level bestimmt, welche Kanäle für welche Notification aktiv sind — ohne Code-Änderungen, wenn sich Routing-Entscheidungen ändern. Eigene Bridges erweitern das System für interne Werkzeuge und Self-hosted Dienste.

Der größte Vorteil von Symfony Notifier liegt in der Testbarkeit: Mit dem Test-Transport werden Notifications nicht wirklich versendet, sondern in einem Array gesammelt. Integrationstests prüfen, ob die richtigen Messages an die richtigen Channels gehen — ohne Slack-Webhooks, Twilio-Account oder echte E-Mail-Zustellung. Die Kombination mit Symfony Messenger für asynchrones Versenden macht Symfony Notifier produktionstauglich: Benachrichtigungen verlangsamen keine HTTP-Requests und werden bei Fehlern automatisch wiederholt.

Symfony Notifier — Das Wichtigste auf einen Blick

Ein Interface, alle Kanäle

NotifierInterface::send() routet Notifications an Chat, SMS, Email und Browser — basierend auf Urgency-Level und Notification::getChannels().

Kanalspezifische Nachrichten

asChatMessage(), asSmsMessage() und asEmailMessage() in der Notification-Klasse liefern kanalspezifische Formate — Block Kit für Slack, Adaptive Cards für Teams.

80+ Bridges

Twilio, Vonage, Slack, Teams, Telegram, PagerDuty, Firebase — oder eigene Bridge für interne Systeme schreiben. Wechsel ist eine Konfigurationszeile.

Async mit Messenger

messenger_bus in notifier.yaml — Notifications landen in der Queue, HTTP-Response bleibt schnell, Retry bei Fehlern automatisch.

11. FAQ: Symfony Notifier

1Was ist Symfony Notifier?
Symfony-Komponente für Multi-Channel-Benachrichtigungen: Slack, Teams, SMS, Email und Browser über ein einheitliches Interface. Über 80 offizielle Bridge-Pakete verfügbar.
2Wie installieren?
composer require symfony/notifier, dann bridge-spezifische Pakete: symfony/slack-notifier, symfony/twilio-notifier etc. Symfony Flex legt Konfiguration automatisch an.
3Chatter vs. Texter vs. Notifier?
Chatter: Chat-Kanäle (Slack, Teams). Texter: SMS-Kanäle. Notifier: koordiniert alle Kanäle und routet basierend auf Urgency und Notification-Konfiguration.
4Slack Block Kit nutzen?
asChatMessage() in der Notification-Klasse gibt ChatMessage mit SlackOptions zurück. Builder-API für Header, Sections, Dividers, Context und Action Blocks — kein JSON manuell schreiben.
5Async mit Symfony Messenger?
messenger_bus in notifier.yaml — Notifications werden in Queue gestellt statt synchron versendet. Jeder Kanal als separate Message, Retry bei Fehlern automatisch.
6Eigene Bridge schreiben?
Transport (HTTP-Anfrage), TransportFactory (DSN parsen), optional Options-Objekt. Factory als Tagged Service registrieren — dann wie offizielle Bridge nutzbar.
7Routing konfigurieren?
channel_policy in notifier.yaml mappt urgent/high/medium/low auf Channel-Listen. getChannels() in der Notification-Klasse überschreibt globales Routing pro Recipient.
8Wie testen?
Eingebauter Test-Transport sammelt Notifications statt zu senden. getSentMessages() in Funktionstests. Kein echter Slack-Webhook oder SMS-Account nötig.
9Welche SMS-Anbieter werden unterstützt?
Twilio, Vonage, Amazon SNS, Sinch, MessageBird, Infobip und weitere. Wechsel des Anbieters = eine neue DSN-Zeile in .env. Handler-Code bleibt identisch.
10Delivery Reports verarbeiten?
Symfony Notifier sendet nur — Delivery Reports kommen als Webhooks vom Anbieter. Symfony-Controller empfängt, verifiziert Signatur und aktualisiert Zustellungsstatus in der DB.