Symfony 7 et Mercure : Implémenter un Live Chat 100% réactif

symfony-mercure-turbo

Introduction

La semaine dernière, nous avons posé les bases : créer un projet Symfony de zéro, exploiter Docker pour gérer toutes les dépendances (base de données, mailer, et bien sûr Mercure pour la diffusion en temps réel).

Si vous avez suivi mon précédent article, vous devriez déjà pouvoir envoyer des messages en temps réel, d’un navigateur à l’autre, sans rechargement et de manière fluide.

👉 Aujourd’hui, on passe à l’étape suivante !
Nous allons :
✅ Créer et gérer des utilisateurs
✅ Reproduire un fil de discussion façon Messenger
✅ Mettre en place l’authentification et l’autorisation pour un chat sécurisé

Alors, prêt à coder un vrai chat live avec Symfony et Mercure ? 🚀

Création des utilisateurs

Maintenant que notre configuration fonctionne, passons à la gestion des utilisateurs. On va utiliser la commande Symfony pour générer notre entité User :

php bin/console make:user

🔹 Clés importantes :

  • On se base sur l’email comme identifiant unique.
  • On sauvegarde le mot de passe dans la base de données (hashé).
  • On utilise Doctrine pour gérer la persistance.

Création de la relation User ↔ Messages

Un utilisateur peut envoyer plusieurs messages, il nous faut donc une relation OneToMany entre User et Message.

Dans User.php, on ajoute :

#[ORM\OneToMany(mappedBy: 'author', targetEntity: Message::class, orphanRemoval: true)]
private Collection $messages;

Pourquoi author et pas user ?
➡️ user est un mot réservé en SQL, donc on préfère author pour éviter les conflits.

on se sert aussi du maker pour éviter les conflits.

Ensuite, on lance la migration :

php bin/console make:migration
php bin/console doctrine:migrations:migration

Notre entité User est prête à envoyer des messages ! 🎉

Inscription et Validation des Comptes

Rien de mieux qu’un PoC pour apprendre et tester efficacement.

Générer le formulaire d’inscription

On utilise une nouvelle fois le Maker Bundle pour créer notre formulaire d’inscription :

php bin/console make:registration-form

On garde les options par défaut, le design n’est pas important pour l’instant.

Vérification des emails

Pour sécuriser l’inscription, on installe le bundle officiel de Symfony :

composer require symfonycasts/verify-email-bundle

➡️ On laisse tout par défaut, on ne touche qu’à la logique.

Protéger l’accès au chat

Dans security.yaml, on protège l’accès à la route /chat :

access_control:
    - { path: ^/chat, roles: ROLE_USER }

👉 Seuls les utilisateurs connectés peuvent accéder au chat.

Processus de validation de l’email

1️⃣ L’utilisateur remplit le formulaire d’inscription et reçoit un email de confirmation grâce à MailCatcher.
2️⃣ Il clique sur le lien, qui contient une URL signée générée par Symfony.
3️⃣ Un middleware intercepte la requête et force l’utilisateur à se connecter avant de valider son compte.
4️⃣ L’URL signée est récupérée par le contrôleur, qui valide définitivement l’utilisateur.

Vérification dans la Debug Bar

Si tout fonctionne, vous devriez voir votre email dans la Debug Bar de Symfony.

✅ Félicitations ! Vous êtes maintenant authentifié, vérifié et enregistré en session. 🎉

Gérer les Messages par Utilisateur

Tout est en place… ou presque ! Avant d’avoir un chat pleinement fonctionnel, il reste quelques ajustements à faire.

Tester la communication en temps réel

Une fois connecté, vous êtes authentifié dans votre navigateur. Mais attention, cela signifie que pour tester la messagerie, vous devez ouvrir deux navigateurs différents (ex: Firefox et Google Chrome).

Pourquoi ?
➡️ Un seul utilisateur ne peut pas s’envoyer des messages à lui-même dans une même session, d’où l’intérêt d’ouvrir deux navigateurs pour simuler deux comptes.

Améliorer l’affichage des messages (CSS & Twig)

Nous devons maintenant ajouter un peu de CSS et remanier notre template Twig pour afficher les messages de façon claire et différenciée.

Voici le Twig Component utilisé pour chaque message :

<div {{ attributes }} 
     class="message-wrapper {% if message.author == app.user %}message-mine{% else %}message-other{% endif %}" 
     id="{{ 'message_' ~ message.id }}">
    
    <div class="message-info">
        <span class="message-author">{{ message.author.email }}</span>
        <span class="message-time">{{ message.createdAt|date('H:i') }}</span>
    </div>
    
    <div class="message-bubble">
        {{ message.content }}
    </div>
</div>

Explication du Code

✅ Les messages sont classés dynamiquement :

  • message-mine → Si le message appartient à l’utilisateur connecté.
  • message-other → Si le message vient d’un autre utilisateur.

✅ Aucune modification sur Mercure ou Twig Blocks
Tout fonctionne grâce aux Turbo Streams, qui permettent d’afficher les nouveaux messages en temps réel sans rechargement.

Test en conditions réelles

1️⃣ Connectez-vous avec deux navigateurs différents.
2️⃣ Accédez à l’URL /chat.
3️⃣ Envoyez des messages et observez la mise à jour instantanée des conversations.

🔹 Résultat ?

  • Les messages apparaissent dans les deux fenêtres simultanément.
  • Ils s’affichent par ordre décroissant, avec des couleurs différentes en fonction de l’expéditeur.

💡 Tout cela est rendu possible grâce à Mercure et Turbo Streams ! 🚀

live chat avec symfony et mercure

🔜 Prochaine Étape : Un Cas Réel

Nous avons maintenant un chat fonctionnel, mais il reste encore du travail ! Pour l’instant, tout le monde peut rejoindre n’importe quelle discussion, ce qui n’est pas idéal.

Ce qui est prévu :

✅ Rechercher un utilisateur et créer un chat privé.
✅ Cloisonner les discussions pour éviter les conversations globales.
✅ Créer des groupes et permettre à plusieurs utilisateurs de rejoindre un fil de discussion.
✅ Ajouter l’upload d’images et pourquoi pas des emojis ? (Ça pourrait être fun 😄).

💡 Bref, l’aventure continue ! Pour l’instant, j’explore ces fonctionnalités et je partagerai bientôt mes tests et découvertes avec Mercure. 🚀

live chat avec symfony 7 et mercure
Notre application turbo-poc à la fin de notre article

Conclusion : Un Chat en Temps Réel, Propulsé par Symfony & Mercure

Que de chemin parcouru ! 🚀

Partant de zéro, nous avons construit un PoC Symfony 7.2 entièrement fonctionnel. Grâce à Docker Compose, nous avons mis en place :
✅ Une base de données PostgreSQL
✅ Un serveur SSE Mercure pour la diffusion en temps réel
✅ Une stack moderne avec PHP 8.4

💡 Résultat ?
Nous avons un chat en temps réel sécurisé, accessible après connexion, où :

  • Les messages sont synchronisés automatiquement entre navigateurs.
  • Le DOM se met à jour sans rechargement grâce à Turbo Streams.
  • Les logs sont conservés et tout fonctionne en SSL.

Symfony et son écosystème nous permettent de créer un projet performant et scalable.

Et maintenant ?

Prochaine étape : passer à un niveau production avec une gestion avancée des utilisateurs et des fils de discussion.

Et toi, es-tu aussi un fan de Symfony et de son incroyable puissance ? 😃

Cet article t’a plu ?

J’essaie autant que possible de consacrer mon temps libre à explorer et approfondir l’écosystème Symfony. D’ailleurs, si cela vous intéresse, j’ai écrit un article sur Doctrine et le cache L2.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *