Retour

Créez un chat avec Mercure et Symfony

Tuto
30 sept. 2020
53mn

À la fin de cette partie, on sera capable d'envoyer nos messages, et nous serons fin prêts à faire intervenir Mercure.

Poster les messages

Pour poster nos messages, nous devons pouvoir les envoyer depuis notre page de chat. Cependant, on souhaite que notre page ne se recharge pas ! Ainsi, nous pourrons profiter du temps réel avec Mercure dans de bonnes conditions. Nous devons donc faire intervenir un peu de JavaScript.

Dans templates/channel/chat.html.twig, ajoutez ce morceau de script, en lisant bien mes commentaires pour comprendre ce qui se passe :

// Dans une balise <script>, et un block {% block javascripts %} let chatDiv = document.querySelector('.overflow-auto'); chatDiv.scrollTop = chatDiv.scrollHeight; // On souhaite scroller toujours jusqu'au dernier message du chat let form = document.getElementById('form'); function handleForm(event) { event.preventDefault(); // Empêche la page de se rafraîchir après le submit du formulaire } form.addEventListener('submit', handleForm); const submit = document.querySelector('button'); submit.onclick = e => { // On change le comportement du submit const message = document.getElementById('message'); // Récupération du message dans l'input correspondant const data = { // La variable data sera envoyée au controller 'content': message.value, // On transmet le message... 'channel': {{ channel.id }} // ... Et le canal correspondant } console.log(data); // Pour vérifier vos informations fetch('/message', { // On envoie avec un post nos datas sur le endpoint /message de notre application method: 'POST', body: JSON.stringify(data) // On envoie les data sous format JSON }).then((response) => { message.value = ''; console.log(response); }); }

Après avoir empêché le navigateur de rafraîchir la page, on utilise l'API fetch et la méthode POST afin d'envoyer le message au serveur et passer outre le fonctionnement natif des formulaires Symfony. Ainsi notre comportement se rapproche un peu plus d'un client communiquant avec son API.

On souhaite que seuls les utilisateurs authentifiés puissent envoyer des messages, alors mettez à jour le pare-feu de security.yaml :

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

Récupérer les messages

Super. L'envoi est fonctionnel et sécurisé. Maintenant, récupérons nos messages depuis le MessageController, via une action sendMessage en méthode POST :

/** * @Route("/message", name="message", methods={"POST"}) */ public function sendMessage( Request $request, ChannelRepository $channelRepository, SerializerInterface $serializer, EntityManagerInterface $em): JsonResponse { $data = \json_decode($request->getContent(), true); // On récupère les data postées et on les déserialize if (empty($content = $data['content'])) { throw new AccessDeniedHttpException('No data sent'); } $channel = $channelRepository->findOneBy([ 'id' => $data['channel'] // On cherche à savoir de quel channel provient le message ]); if (!$channel) { throw new AccessDeniedHttpException('Message have to be sent on a specific channel'); } $message = new Message(); // Après validation, on crée le nouveau message $message->setContent($content); $message->setChannel($channel); $message->setAuthor($this->getUser()); // On lui attribue comme auteur l'utilisateur courant $em->persist($message); $em->flush(); // Sauvegarde du nouvel objet en DB $jsonMessage = $serializer->serialize($message, 'json', [ 'groups' => ['message'] // On serialize la réponse avant de la renvoyer ]); return new JsonResponse( // Enfin, on retourne la réponse $jsonMessage, Response::HTTP_OK, [], true ); }

Après avoir décodé le message reçu et avoir validé qu'il corresponde aux données attendues, on a créé un nouvel objet Message, qu'on a serializé avec le serialization group message. Puis on le retourne donc sous format Json. Pour savoir quelles propriétés de notre entité on souhaite serializer, on utilise l'annotation @Groups() sur ces dernières, comme ceci :

/** * @ORM\Column(type="string", length=255) * @Groups("message") */ private string $content;

À minima, ajoutez ce groupe sur les propriétés $id, $content, $channel, $author de l'entité Message.

Vous pouvez dès à présent tenter d'envoyer un message. Rafraîchissez la page afin de constater que le message a bien été envoyé, et s'affiche bien dans le chat.

Pas très pratique d'avoir fait tout ca pour simplement recharger manuellement notre page

Il est temps de passer au temps réel avec Mercure.

Vous pouvez vous rendre sur cette branche pour être à jour sur cette étape du tutoriel, et continuer sereinement vers la prochaine partie.


Articles sur le même thème

Découvrez Eleven Labs

Notre site pour mieux nous connaître

J'y vais

Contact

Eleven Labs - Paris

102, rue du Faubourg Saint Honoré

75008 Paris

Eleven Labs - Nantes

42, rue la Tour d'Auvergne

44200 Nantes

Eleven Labs - Montréal

1155, Metcalfe St Suite 1500

Montréal, QC H3B 2V6, Canada

business@eleven-labs.com

01.82.83.11.75