Archives Wild Code School
Symfony

17 - Symfony : Sessions et messages flash

Quête 20 sur 35 · 1 image archivée

Objectifs

  • ✅ Utiliser les sessions sous Symfony
  • ✅ Comprendre le principe de fonctionnement des messages flash
  • ✅ Mettre en place et afficher des messages flash

Pré-requis

​ Avoir terminé la quête

Quêtes liées
title-book
Introduction

Dans une application, tu as souvent besoin de persister des informations d’une page à l’autre, sans nécessairement les enregistrer en base de données (un panier sur un site e-commerce par exemple). Les sessions sont là pour résoudre ce type de problématique fréquente, comme tu as déjà pu le découvrir dans une précédente quête dédiée.

D’autre part, il est très souvent nécessaire d’afficher des messages de notification pour informer les utilisateurs, confirmer une action de leur part, indiquer une erreur, etc.

Les messages flash sont un type de notification basé sur les sessions. Leur particularité est de ne s’afficher qu’une seule fois. Après tout changement ou rechargement de page, ils disparaissent. Cela répond exactement à ce que tu as besoin d’afficher après une soumission de formulaire, (ajout/suppression/édition, confirmation d’envoi d’un mail, etc.) et c’est principalement pour cela que les messages flash sont utilisés.

Sommaire

Les sessions sous Symfony

Tu vas voir dans cette partie comment utiliser les sessions avec Symfony. La première règle, c’est que contrairement à ce que tu as pu faire jusqu’ici, tu n’utiliseras JAMAIS directement la variable superglobale $_SESSION.

Tu utiliseras à la place une surcouche objet (ce qui est plus logique dans une approche intégralement POO et facilite également les tests).

Pas de panique, tout cela est très simple. Pour utiliser les sessions, il faut récupérer un objet de type Session, depuis un objet RequestStack. Grâce au type hinting, tu vas injecter l’objet RequestStack dans ton contrôleur (ou dans un Service) puis utiliser sa méthode getSession():

php
use Symfony\Component\HttpFoundation\Session\SessionInterface;

#[Route('/program')]
class ProgramController extends AbstractController
{
    #[Route('/', name:'program_index')]
    public function index(RequestStack $requestStack) : Response
    {
        $session = $requestStack->getSession();
        // some code using $session
    }
}
Info

Dans Symfony, il n’est pas nécessaire de démarrer la session via session_start(), cela est géré automatiquement dès qu’une session est requise.

Ensuite, plutôt que d’ajouter ou supprimer une clé/valeur au tableau $_SESSION, tu auras accès à différentes méthodes de l’objet $session, dont les trois principales :

  • La méthode has() qui permet de tester l’existence d’une clé en session,

  • La méthode set() qui permet d’ajouter une paire clé/valeur à la session,

  • La méthode get() qui permet de récupérer la valeur associée à une clé en session,

Imaginons que l'on souhaite récupérer un total antérieurement stocké en session :

php
public function index(RequestStack $requestStack) : Response
{
    $session = $requestStack->getSession();
    if (!$session->has('total')) {
        $session->set('total', 0); // if total doesn’t exist in session, it is initialized.
    }

    $total = $session->get('total'): // get actual value in session with ‘total' key.
    // ...
}

Pour afficher les données en session, tu pourrais envoyer ici $total (récupéré dans le contrôleur depuis la session) à ta vue Twig. Cependant, pour te faciliter encore davantage la tâche, Twig peut accéder directement aux données de session, sans passer par une récupération dans le contrôleur. C’est utile si tu n’as pas à modifier les informations en session, mais seulement à les afficher.

Pour cela, tu feras :

twig
{{ app.session.get('total') }}
↗
Afficher les sessions dans Twig
symfony.com
↗
Documentation officielle sur les sessions
symfony.com

Principe de fonctionnement des messages flash

Les messages flash se basent sur les sessions. Chaque message est placé en attente (dans un tableau, le flashbag) jusqu’au moment où tu demandes de l’afficher. Ensuite, dès qu’il s’affiche, le message est “supprimé” du flashbag. Il ne s'affiche donc qu’une et une seule fois, d’où le nom de message flash.

On peut conditionner l'affichage des messages à un seul type de message. Dans ce cas, les messages qui n'ont pas été affichés sont conservés dans le flashbag (voir illustration ci-dessous).

Symfony flash bag

Utilisation des messages flash avec Symfony

Tu pourrais utiliser directement les sessions pour ajouter et supprimer tes messages flash de ton flashbag. Cependant, Symfony t’apporte différentes méthodes et helper twig pour te faciliter la vie. De ce fait, quand tu utilises les messages flash, tu ne feras pas directement appel à un objet Session, mais à des méthodes spécifiques qui, indirectement, utilisent Session.

Ecrire un message flash

Le but d’un message flash est généralement de faire suite à une action d’un utilisateur, le plus souvent la soumission d’un formulaire. Dans ce cas, le message doit s’inscrire dans le contrôleur une fois que tu t’es assuré que la soumission a été correctement effectuée, mais tout de même avant d’être redirigé vers une autre page :-)

Voici un exemple basique de l’ajout d’une série, pour illustrer où tu dois placer le message.

php
#[Route('/new', name: 'program_new', methods: ['GET', 'POST'])]
public function new(
    Request $request,
    EntityManagerInterface $entityManager
): Response {
   $program = new Program();
   $form = $this->createForm(ProgramType::class, $program);
   $form->handleRequest($request);

   if ($form->isSubmitted() && $form->isValid()) {
       $entityManager->persist($program);
       $entityManager->flush();

       // Once the form is submitted, valid and the data inserted in database, you can define the success flash message
       $this->addFlash('success', 'The new program has been created');

       return $this->redirectToRoute('program_index');
   }

   return $this->render('program/new.html.twig', [
       'program' => $program,
       'form' => $form,
   ]);
}

Comme tu peux le voir, il faut tout simplement utiliser la méthode $this->addFlash() qui prend deux paramètres : la catégorie du message et le message lui-même. La catégorie est libre, tu peux mettre ce que tu veux. Le but est de pouvoir regrouper ensemble les messages d’un même type, de décider lesquels afficher et de les styliser différemment en fonction. Par convention, un message de succès s’affiche généralement en vert, un message d’erreur en rouge, etc. Tout cela est libre, mais par simplification, il est commode d’utiliser des classes CSS (celles de Bootstrap si tu utilises ce framework CSS) comme noms de catégorie pour tes messages.

Affichage des messages

CSS ? Bootstrap ? Tu vas mieux comprendre dans un instant. Pour afficher les messages flash, il faut l’indiquer spécifiquement dans un fichier Twig (tu te souviens, Twig peut accéder directement aux sessions), grâce à app.flashes (qui correspond au flashbag, le tableau contenant tous les messages flash)

html
{% for category, messages in app.flashes %}
    {% for message in messages %}
        <div class="alert alert-{{ category }}">
            {{ message }}
        </div>
    {% endfor %}
{% endfor %}

Dans la première boucle, tu récupères la clé “category” ("success", "warning"...) et les messages associés à cette catégorie, puis tu effectues une seconde boucle qui va afficher dans une div tous les messages d’une catégorie donnée (tu pourrais ici ajouter une condition pour n’afficher que les messages d’une catégorie précise, si cela t’était nécessaire). Tu remarques que le div possède un attribut class="alert alert-{{category}}". Toute l’astuce se trouve ici, car si tu as bien utilisé les mêmes noms que ceux de Bootstrap (success, danger, info, warning…), tu affiches pour chacun d’entre eux une alert stylisée de la bonne couleur, très simplement.

Ensuite, dès que les messages vont être affichés dans Twig, ils seront également supprimés du flashbag et ne s’afficheront plus.

Info

Si tu souhaites afficher les messages flash sur une page mais que tu oublies de configurer leur affichage dans le Twig, ceux-ci restent dans le flashbag et apparaîtront sur la prochaine page rencontrée qui, elle, affichera les messages flash. Le risque est que tu affiches une notification qui n’a plus rien à voir avec la page sur laquelle tu te trouves. Pour éviter ce type de problème, il est très fortement conseillé d’afficher les messages flash sur toutes tes pages Twig. Pour ce faire simplement, il suffit d’appeler le code qui affiche les messages directement dans le fichier base.html.twig, dont tous tes autres fichiers Twig doivent normalement hériter. Problème résolu !

↗
Définir un message flash

depuis le contrôleur.

symfony.com
↗
Rappel sur le composant alert de Bootstrap

Si tu utilises une autre librairie CSS (ou ton propre style), il te suffit de personnaliser la ligne gérant l’affichage du message.

getbootstrap.com

💪 Challenge

Configure les messages flash sur ton Wild Series

Le challenge est simple. Une fois l’affichage des messages flash configuré dans ton fichier base.html.twig, fais en sorte d’ajouter un message de type “success” pour tous les ajouts ou éditions de série, saison ou épisode. De plus, ajoute un message de type “danger” qui indiquera qu'une série, saison ou épisode a bien été supprimé(e).

Critères de validation

  • L’affichage des messages flash est correctement configuré dans le fichier base.html.twig
  • L’ajout et l’édition d’une série, saison ou épisode affichent un message flash vert (reprenant le style de la classe “alert-success” de Bootstrap par exemple) pour confirmer la réussite de la modification.
  • La suppression d’une série, saison ou épisode affiche un message flash rouge (reprenant le style de la classe “alert-danger” de Bootstrap par exemple) pour confirmer la réussite de la suppression.
  • Le code est disponible sur un repository GitHub, avec une branche correspondant à cette quête.