Ü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:
- Basiert auf SSE: Verwendet Server-Sent Events, nativ in modernen Browsern unterstützt
- Autorisierungsmechanismus: Eingebautes Authentifizierungssystem
- Automatische Wiederverbindung: Mit Wiederherstellung verlorener Updates
- Presence API: Erfahren Sie, welche Benutzer verbunden sind
- Verbindungsloser Push: Für Smartphones
- 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
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