Introduction
Symfony, grâce à ses paquets UX, ouvre la porte à de nombreuses possibilités pour améliorer l’expérience utilisateur. Ce Proof of Concept (POC) va nous permettre d’explorer ces outils en créant un chat en temps réel avec Symfony UX Turbo, Mercure et Server-Sent Events (SSE).
Bien sûr, un chat en direct peut être implémenté de manière basique avec AJAX, mais cette approche est gourmande en ressources. Pourquoi laisser un script effectuer des requêtes constantes alors qu’il ne se passe peut-être rien ?
C’est ici que la magie du SSE (Server-Sent Events) entre en jeu. Plutôt que de recharger inutilement, le serveur enverra automatiquement les nouveaux messages aux utilisateurs connectés sans polling ni WebSockets complexes.
Dans cette première version, nous allons développer un chat en temps réel sans authentification, une simple exploration des possibilités offertes par Symfony et Mercure.
🎯 Objectif : Lorsqu’un utilisateur envoie un message, le DOM est mis à jour automatiquement sur toutes les fenêtres ouvertes et sur différents navigateurs, à la manière de Facebook Messenger.
Prêt ? C’est parti ! 🚀
Installation et Configuration des Paquets
Avant de plonger dans le code, commençons par installer Symfony et préparer notre environnement.
symfony new turbo-poc --version="7.2.x" --webapp
cd turbo-poc
Création de l’entité Message
Notre chat repose sur une entité Message simple. Créons-la avec le maker :
php bin/console make:entity Message
Ajoutons ensuite quelques champs :
id
(généré automatiquement)content
(le contenu du message)createdAt
(la date d’envoi du message)
Puis on met à jour la base de données
php bin/console doctrine:migrations:migrate
Installation et Configuration de Mercure
Mercure est essentiel pour la communication en temps réel. Installons-le avec Composer :
composer require symfony/mercure-bundle
Lancement de Docker avec Mercure
On utilise Docker pour gérer Mercure et la base de données. Démarrons tout avec :
docker-compose up -d
On vérifie que tout est bien configuré, notamment :
✅ La base de données est connectée
✅ Mercure fonctionne correctement
Création de la Route Home
Pour gagner du temps, créons rapidement une route Home avec le Maker :
php bin/console make:controller HomeController
On est prêts ! 🎉 La base du projet est saine et on peut maintenant attaquer la partie temps réel.
Comment Fonctionne le Chat en Temps Réel ?
L’un des plus grands atouts de Symfony UX Turbo et Mercure est leur capacité à gérer automatiquement la diffusion des mises à jour sans écrire une seule ligne de code JavaScript.
Diffusion Automatique avec Mercure et l’Attribut #[Broadcast]
Grâce à l’attribut #[Broadcast(topics:['chat'])]
, chaque utilisateur est automatiquement abonné au chat via Mercure.
📡 Concrètement, voici ce qui se passe :
- L’attribut
#[Broadcast]
inscrit l’entitéMessage
au hub Mercure. - Mercure agit comme un serveur SSE (Server-Sent Events), émettant en temps réel les modifications de la base de données vers tous les clients connectés.
- Aucune requête AJAX, aucun polling ! 🎉
- Les événements CRUD (
create
,update
,delete
) sont natifs, donc aucun code JavaScript n’est nécessaire pour gérer la mise à jour du chat !
En bref : on écrit un message, il est instantanément diffusé à tous les utilisateurs connectés. 🚀
Turbo Streams : Mise à Jour du DOM Sans Rechargement
Turbo Streams, l’un des outils de Turbo, permet de modifier le DOM en temps réel. Plutôt que de recharger toute la page, il cible directement l’élément à modifier via son id
.
🔎 Notre approche :
✅ À chaque envoi d’un message, l’EntityManager le persiste en base.
✅ Cela déclenche automatiquement un événement Mercure (grâce à #[Broadcast]
).
✅ Turbo Streams capte cet événement et met à jour le DOM à la volée, en se basant sur l’id
du message.
👉 Résultat : le chat est instantanément mis à jour sur toutes les fenêtres ouvertes et tous les navigateurs, sans effort supplémentaire !
Pourquoi c’est révolutionnaire ?
✅ Pas de JavaScript complexe à gérer
✅ Aucune requête AJAX
✅ Zéro polling, donc économie de ressources serveur
✅ Un chat en temps réel ultra-performant en quelques lignes de code
C’est tout simplement magique ✨ !
Et le code alors ?
Le code du controller
#[Route('/', name: 'app_home')]
public function index(Request $request, EntityManagerInterface $entityManager, MessageRepository $messageRepository): Response
{
$message = new Message();
$form = $this->createForm(ChatType::class, $message);
$emptyForm = clone $form;
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->persist($message);
$entityManager->flush();
$form = $emptyForm;
}
return $this->render('home/index.html.twig', [
'form' => $form,
'messages' => $messageRepository->findBy([], ['createdAt' => 'DESC']),
]);
}
Et le front ?
{% extends 'base.html.twig' %}
{% block title %}Hello HomeController!{% endblock %}
{% block body %}
<main class="container">
<h2>Derniers messages</h2>
<div class="grid" id="messages" {{ turbo_stream_listen('chat') }}>
{% for message in messages %}
<twig:MessageComponent :message="message"></twig:MessageComponent>
{% endfor %}
</div>
<turbo-frame id="message_form">
{{ form_start(form) }}
{{ form_widget(form) }}
<button>Envoyer</button>
{{ form_end(form) }}
</turbo-frame>
</main>
{% endblock %}
L’entité Message
<?php
namespace App\Entity;
use App\Repository\MessageRepository;
use DateTimeImmutable;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Symfony\UX\Turbo\Attribute\Broadcast;
#[ORM\Entity(repositoryClass: MessageRepository::class)]
#[Broadcast(topics:['chat'])]
class Message
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(type: Types::TEXT)]
private ?string $content = null;
Ici je me sers d’un twig component, mais ce n’est pas obligatoire, c’est juste un plus.
✅ Ce que ce Code Fait
🔥 Ajout d’un message → Dès qu’un utilisateur soumet un message, Symfony UX Turbo met à jour instantanément le chat sans recharger la page.
🚀 Diffusion via Mercure → Mercure envoie automatiquement l’événement SSE à tous les clients connectés.
💡 Turbo Streams → Gère la mise à jour du DOM sans JavaScript.
🎯 Résultat Final
➡️ Un chat en temps réel 100% Symfony
➡️ Aucune requête AJAX, aucun WebSocket
➡️ Optimisé pour la performance
La vidéo final :

De nombreux développeurs, notamment sur Reddit, expriment leur enthousiasme face aux possibilités offertes par Symfony UX Turbo. Grâce à son intégration native avec Mercure, il simplifie grandement la gestion des mises à jour en temps réel sans effort côté front-end.
L’un des points les plus appréciés est que Turbo fonctionne automatiquement avec Symfony et Mercure, sans nécessiter de configuration complexe. Cette approche séduit de plus en plus de développeurs qui recherchent une solution performante et moderne pour gérer des interactions dynamiques sans avoir à manipuler manuellement les WebSocketsou l’AJAX polling.
🚀 Les retours sont majoritairement positifs, et beaucoup considèrent Symfony UX Turbo comme une alternative puissante aux solutions classiques pour le développement d’applications interactives en temps réel.
Conclusion
À première vue, ce Proof of Concept (POC) peut sembler simpliste, mais il démontre toute la puissance des Server-Sent Events (SSE) lorsqu’ils sont combinés avec Symfony UX Turbo et Mercure.
🔥 En seulement 30 minutes, nous avons développé un chat en temps réel sans écrire une seule ligne de JavaScript, tout en profitant d’un protocole léger, efficace et scalable.
🚀 La suite ?
Dans un prochain article, nous ajouterons la gestion des sessions pour transformer ce chat en un mini-clone de Messenger, avec un suivi des conversations et toujours 100% Turbo !
Avec ses outils Turbo Drive, Turbo Streams et Turbo Frames, Turbo offre une flexibilité incroyable pour mettre à jour le DOM en temps réel et optimiser l’expérience utilisateur sans complexité.
Symfony + Turbo + Mercure = Une solution moderne et performante pour le temps réel !
Cet article t’a plu ?
Cet article est le début d’une longue série sur les paquets UX.
Voici le lien du dépôt Github pour retrouver le code source
Laisser un commentaire