Daten an Clients mit dem Mercure-Protokoll senden

Dec 07, 2025 2 Min. Lesezeit 426 Aufrufe
Daten an Clients mit dem Mercure-Protokoll senden

Überblick

Das Übertragen von Daten in Echtzeit von Servern zu Clients ist eine wesentliche Anforderung für viele moderne Web- und Mobile-Anwendungen.

Häufige Anwendungsfälle:

  • Erstellung von Benutzeroberflächen, die live auf Änderungen anderer Benutzer reagieren
  • Benachrichtigung der Benutzer, wenn asynchrone Aufgaben abgeschlossen sind
  • Entwicklung von Chat-Anwendungen

Was ist Mercure?

Mercure ist ein offenes Protokoll, das speziell entwickelt wurde, um Updates von Servern an Clients zu senden. Es ist eine moderne und effiziente Alternative zu:

  • Timer-basiertem Polling
  • WebSocket

Hauptmerkmale:

  1. Basiert auf SSE: Verwendet Server-Sent Events, nativ in modernen Browsern unterstützt
  2. Autorisierungsmechanismus: Eingebautes Authentifizierungssystem
  3. Automatische Wiederverbindung: Mit Wiederherstellung verlorener Updates
  4. Presence API: Erfahren Sie, welche Benutzer verbunden sind
  5. Verbindungsloser Push: Für Smartphones
  6. Automatische Erkennung: Clients können Updates automatisch entdecken und abonnieren

Installation

Symfony-Bundle installieren:

composer require mercure

Mercure Hub starten:

Mercure basiert auf einem Hub (zentraler Verteiler) zur Verwaltung persistenter Verbindungen. Die Symfony-App veröffentlicht Updates an den Hub, der sie an die Clients sendet.

[Symfony-App] --POST--> [Mercure Hub] --SSE--> [Clients]

Konfiguration

Wichtige Umgebungsvariablen:

Variable Beschreibung
MERCURE_URL Lokale URL für den Hub (verwendet von der Symfony-App)
MERCURE_PUBLIC_URL Öffentliche URL (verwendet von Browser-JavaScript)
MERCURE_JWT_SECRET Geheimer Schlüssel zum Signieren von JWTs

Konfigurationsbeispiel (YAML):

# config/packages/mercure.yaml
mercure:
    hubs:
        default:
            url: '%env(string:MERCURE_URL)%'
            public_url: '%env(string:MERCURE_PUBLIC_URL)%'
            jwt:
                secret: '%env(string:MERCURE_JWT_SECRET)%'

Grundlegende Verwendung

Veröffentlichen (Publishing):

namespace App\Controller;

use Symfony\Component\Mercure\HubInterface;
use Symfony\Component\Mercure\Update;

class PublishController extends AbstractController
{
    public function publish(HubInterface $hub): Response
    {
        // Neues Update erstellen
        $update = new Update(
            'https://example.com/books/1',  // Thema (Topic)
            json_encode(['status' => 'OutOfStock'])  // Daten
        );

        // Update veröffentlichen
        $hub->publish($update);

        return new Response('Veröffentlicht!');
    }
}

Hinweise:

  • Erster Parameter (topic): Eindeutiger Bezeichner für die Ressource (normalerweise URL oder IRI)
  • Zweiter Parameter: Update-Inhalt (JSON oder XML empfohlen)

Abonnieren (Subscribing):

In einem Twig-Template:

<script>
const eventSource = new EventSource("{{ mercure('https://example.com/books/1') }}");
eventSource.onmessage = event => {
    // Wird bei jedem veröffentlichten Update aufgerufen
    console.log(JSON.parse(event.data));
}
</script>

Mehrere Themen abonnieren:

const eventSource = new EventSource("{{ mercure([
    'https://example.com/books/1',
    'https://example.com/books/2',
    'https://example.com/reviews/{id}'  // URI-Template
]) }}");

Erkennung (Discovery)

Symfony kann die Hub-URL in einem HTTP-Header bereitstellen:

use Symfony\Component\Mercure\Discovery;

class DiscoverController extends AbstractController
{
    public function discover(Request $request, Discovery $discovery): JsonResponse
    {
        // Fügt hinzu: Link: <https://hub.example.com/.well-known/mercure>; rel="mercure"
        $discovery->addLink($request);

        return $this->json(['@id' => '/books/1']);
    }
}

Autorisierung

Private Updates:

Um Updates nur an autorisierte Benutzer zu senden:

$update = new Update(
    'https://example.com/books/1',
    json_encode(['status' => 'OutOfStock']),
    true  // Privates Update
);

Private Updates abonnieren:

<script>
const eventSource = new EventSource(
    "{{ mercure('https://example.com/books/1', { subscribe: 'https://example.com/books/1' }) }}",
    { withCredentials: true }  // Wichtig für das Senden von Cookies
);
</script>

Testen

Unit-Tests:

use Symfony\Component\Mercure\MockHub;

$hub = new MockHub(
    'https://internal/.well-known/mercure',
    new StaticTokenProvider('foo'),
    function(Update $update): string {
        return 'id';
    }
);

API Platform Integration

use ApiPlatform\Core\Annotation\ApiResource;

#[ApiResource(mercure: true)]  // Automatisches Broadcasting aktivieren
#[ORM\Entity]
class Book
{
    public string $name = '';
    public string $status = '';
}

Dies ermöglicht automatisches Update-Broadcasting, wenn ein Buch erstellt, geändert oder gelöscht wird.


Zusammenfassung

Konzept Erklärung
Mercure Protokoll für Echtzeit-Datenübertragung
Hub Vermittelnder Server zur Verbindungsverwaltung
Topic Eindeutiger Bezeichner für die aktualisierte Ressource
SSE Browser-Technologie zum Empfangen von Updates
JWT Token für Authentifizierung und Autorisierung

Quelle: symfony docs v 6.4

Diesen Beitrag teilen

AM

Autor Amer Malik Mohammed

Full-Stack Entwickler mit 2+ Jahren Erfahrung in objektorientierter PHP-Entwicklung (Symfony), JavaScript und MySQL. Spezialisiert auf E-Commerce-Lösungen (Shopware 5/6), REST-API-Entwicklung und Prozessautomatisierung in agilen Teams.

Autor kontaktieren