Aller au contenu principal

Publier un événement

Créer le contrôleur d'administration qui publie une mise à jour de statut en temps réel vers le Hub Mercure

Petite vérification​

Avant de commencer, vérifiez si vous savez...

  1. dans le projet symfolivraison, ouvrir le fichier .env et vérifier la présence des 3 variables MERCURE_URL, MERCURE_PUBLIC_URL et MERCURE_JWT_SECRET
  2. démarrer le serveur avec symfony serve et accéder à https://localhost/.well-known/mercure pour vérifier que le Hub répond bien
  3. dans le terminal, vérifier que le paquet symfony/mercure-bundle a bien été installé (par exemple en consultant composer.json)
📌 Réponse attendue

Notions théoriques​

La classe Update​

Pour publier une mise à jour, Mercure utilise la classe Update du composant symfony/mercure. Elle prend deux paramètres obligatoires :

use Symfony\Component\Mercure\Update;

$update = new Update(
'https://monapp.fr/livraison/42', // 1. le topic
json_encode(['statut' => 'Expédiée']) // 2. les données (JSON)
);
  • Le topic identifie la ressource mise à jour (une URL unique par ressource)
  • Les données sont une chaîne JSON transmise à tous les subscribers du topic
info

Il est recommandé de sérialiser les données en JSON avec json_encode(). Les subscribers JavaScript peuvent alors les désérialiser facilement avec JSON.parse().

L'interface HubInterface​

Pour envoyer l'Update vers le Hub, Symfony injecte automatiquement l'interface HubInterface dans le contrôleur (ou tout service). Cette interface expose une unique méthode : publish().

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

public function changerStatut(HubInterface $hub): Response
{
$update = new Update(
'https://monapp.fr/livraison/42',
json_encode(['statut' => 'Expédiée'])
);

$hub->publish($update); // ← envoie l'Update au Hub

return new Response('Mise à jour envoyée !');
}
astuce

HubInterface est autowirable — Symfony l'injecte automatiquement dans vos contrôleurs et services par le système d'injection de dépendances, sans configuration supplémentaire.

Construction du topic dans SymfoLivraison​

Dans notre projet, le topic est construit à partir de l'identifiant de la livraison :

https://symfolivraison.local/livraison/{id}

Chaque client s'abonnera uniquement au topic de sa livraison et ne recevra que les mises à jour qui le concernent. Un admin qui change le statut de la livraison n°3 ne déclenchera aucune mise à jour sur la page de suivi de la livraison n°7.

Exemple de mise en application​

Voici le contrôleur d'administration complet qui publie un changement de statut via Mercure :

<?php
// src/Controller/Admin/LivraisonController.php
namespace App\Controller\Admin;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Mercure\HubInterface;
use Symfony\Component\Mercure\Update;
use Symfony\Component\Routing\Attribute\Route;

class LivraisonController extends AbstractController
{
private const TOPIC_PREFIX = 'https://symfolivraison.local/livraison/';

private const STATUTS_VALIDES = [
'En préparation',
'Expédiée',
'En cours de livraison',
'Livrée',
];

#[Route('/admin/livraison/{id}/statut/{statut}', name: 'admin_livraison_statut')]
public function changerStatut(int $id, string $statut, HubInterface $hub): Response
{
if (!in_array($statut, self::STATUTS_VALIDES)) {
return $this->json(['error' => 'Statut invalide'], 400);
}

$update = new Update(
self::TOPIC_PREFIX . $id,
json_encode(['id' => $id, 'statut' => $statut])
);

$hub->publish($update);

return $this->json(['success' => true, 'statut' => $statut]);
}
}
attention

Notez la validation du statut (in_array) avant de publier : sans elle, n'importe qui pourrait appeler cette URL avec n'importe quelle valeur. En production, cette route devrait également être protégée par un contrôle d'accès (security.yaml).

Test de mémorisation/compréhension​


Quelle classe Mercure représente une mise à jour à publier ?


Quel est le premier paramètre du constructeur de la classe Update ?


Comment Symfony injecte-t-il HubInterface dans un contrôleur ?


Sous quel format les données d'une Update Mercure sont-elles habituellement encodées ?


Quelle méthode de HubInterface déclenche l'envoi d'une Update vers les subscribers ?


Pourquoi est-il important de valider la valeur du statut avant de la publier via Mercure ?


TP pour réfléchir et résoudre des problèmes​

Étape 1 — Créer le contrôleur d'administration​

Dans src/Controller/Admin/, créez le fichier LivraisonController.php.

Bonne pratique - Sous-espaces de noms pour les contrôleurs admin

Regrouper les contrôleurs d'administration dans Controller\Admin\ permet de séparer clairement les routes publiques des routes réservées aux administrateurs. Cela facilite l'application de règles de sécurité globales dans security.yaml (ex : path: ^/admin → rôle requis).

Étape 2 — Ajouter les imports nécessaires​

Bonne pratique - Regrouper les imports par namespace

Classez les use par ordre alphabétique du namespace. Cela facilite la lecture et évite les doublons dans les projets en équipe.

Étape 3 — Implémenter la méthode changerStatut​

Bonne pratique - Utiliser une constante pour le préfixe du topic

Définissez le format du topic dans une constante de classe (TOPIC_PREFIX) plutôt qu'en dur dans chaque méthode. Cette valeur sera réutilisée dans la séance suivante pour la souscription côté client — une seule modification suffit si l'URL change.

📌 Une solution