Chapitre 4.5 — Sessions & messages flash
Partie 4 : Cœur HTTP — Chapitre 5/6 Version de référence : Symfony 7.4.
⏱️ TL;DR
- Une session conserve un état entre les requêtes d’un même utilisateur (panier, préférences, étape d’un tunnel), stocké côté serveur, référencé par un cookie de session.
- On y accède via l’objet
Request($request->getSession()) ou en injectantSessionInterface/RequestStack.- Un message flash est une donnée éphémère stockée en session, lue une seule fois (à la requête suivante) — parfait pour « Réservation confirmée ✅ » après une redirection.
- Attention en API : une API stateless (JWT) n’utilise pas de session. Les sessions sont pour le back-office full-stack (Twig), pas pour l’API consommée par Next.js.
- Pour un dev Next.js : la session Symfony ≈ une session serveur classique (cookie + store), à l’opposé du modèle stateless JWT que vous privilégierez pour l’API.
🎯 Objectifs
- Lire et écrire dans la session.
- Utiliser les messages flash après une redirection.
- Savoir quand la session est pertinente… et quand il faut l’éviter (API stateless).
1. La session : de l’état entre les requêtes
HTTP est sans état : chaque requête est indépendante. La session ajoute une mémoire par utilisateur. Symfony gère un cookie (PHPSESSID ou nom configuré) qui identifie la session ; les données réelles sont côté serveur (fichiers, base, Redis…).
use Symfony\Component\HttpFoundation\Request;
#[Route('/cart/add/{id}', methods: ['POST'])]
public function addToCart(int $id, Request $request): Response
{
$session = $request->getSession();
$cart = $session->get('cart', []); // lit (défaut : tableau vide)
$cart[] = $id;
$session->set('cart', $cart); // écrit
return $this->redirectToRoute('cart_show');
}Méthodes principales : get($key, $default), set($key, $value), has($key), remove($key), clear(). La session démarre automatiquement dès qu’on y écrit, et le cookie est envoyé via kernel.response.
⚠️ Piège : n’entassez pas de gros objets ou des entités Doctrine complètes en session (sérialisation lourde, données périmées). Stockez des identifiants ou des données minimales (ex. la liste des
iddu panier), et rechargez les entités depuis la base au besoin.
2. Les messages flash
Un flash est une donnée en session qui survit exactement à une redirection puis disparaît. C’est le mécanisme standard du pattern POST → Redirect → GET : on traite un POST, on redirige, et la page cible affiche un message de confirmation.
// après une action réussie
$this->addFlash('success', 'Réservation confirmée !');
return $this->redirectToRoute('booking_list');Côté template (Partie 7), on les affiche puis ils sont consommés :
{# templates/base.html.twig #}
{% for label, messages in app.flashes %}
{% for message in messages %}
<div class="flash flash-{{ label }}">{{ message }}</div>
{% endfor %}
{% endfor %}Les « labels » (success, error, warning, info) sont libres — ils servent à styliser. Après affichage, le flash est retiré de la session : rafraîchir la page ne le remontre pas.
💡 Pour un dev Next.js : le message flash n’a pas d’équivalent direct côté SPA (vous géreriez un toast dans un state client). C’est un pattern full-stack (rendu serveur) : la donnée voyage dans la session le temps d’une redirection. Vous l’utiliserez dans le back-office Twig de BookLab, pas dans l’API.
3. Quand utiliser la session — et quand l’éviter
- Back-office full-stack (Twig) : la session est naturelle et pratique (auth par cookie de session, flash, tunnels multi-étapes).
- API headless (Next.js) : on veut une API stateless — chaque requête porte son jeton (JWT), sans état serveur partagé. Pas de session, pas de flash. C’est plus scalable (aucune affinité de session entre serveurs) et adapté à un front découplé.
C’est précisément la double nature de BookLab : le back-office admin utilise l’auth par session (Partie 10), tandis que l’API pour Next.js utilise JWT sans session. Le composant Security gère les deux via des firewalls distincts (Partie 10).
⚠️ Piège API : activer les sessions sur les routes d’API « par réflexe » casse le côté stateless (cookies inutiles, affinité de session, surface CSRF). Pour l’API, on désactive la session sur le firewall concerné (
stateless: true). On le configurera en Partie 10.
4. Où sont stockées les sessions
Par défaut, en fichiers (dossier var/). En production multi-serveurs, on utilise un stockage partagé : Redis (recommandé), une base de données, etc. — sinon un utilisateur « saute » de session en passant d’un serveur à l’autre. La configuration se fait dans config/packages/framework.yaml (framework.session.handler_id). On y revient en Partie 15 (perf/prod).
✏️ Exercices
Exercice 1. Écrivez une action qui incrémente un compteur de visites stocké en session et l’affiche.
✅ Solution
#[Route('/visits', methods: ['GET'])]
public function visits(Request $request): Response
{
$session = $request->getSession();
$count = $session->get('visits', 0) + 1;
$session->set('visits', $count);
return $this->json(['visits' => $count]);
}(Exemple pédagogique ; en pratique, un compteur de visites relèverait plutôt d’analytics, pas de la session.)
Exercice 2. Après avoir créé une réservation dans le back-office, vous voulez afficher « Réservation créée » sur la page de liste. Décrivez le mécanisme complet.
✅ Solution
Pattern POST → Redirect → GET avec flash : dans l’action POST, après création, $this->addFlash('success', 'Réservation créée') puis return $this->redirectToRoute('booking_list'). La page de liste (GET), via base.html.twig, itère sur app.flashes et affiche le message. Le flash est consommé après affichage : un rafraîchissement ne le remontre pas. On évite ainsi la re-soumission du formulaire au rechargement.
Exercice 3. Pourquoi l’API de BookLab consommée par Next.js n’utilise-t-elle pas de session ?
✅ Solution
Parce qu’on veut une API stateless : chaque requête porte son JWT (auto-suffisant), sans état serveur ni cookie de session. Avantages : scalabilité (aucune affinité de session entre serveurs), simplicité côté front découplé, moins de surface CSRF. La session reste réservée au back-office Twig. Les deux mondes coexistent via des firewalls distincts (Partie 10).
🧠 Quiz de révision
1. À quoi sert une session ?
À conserver un état entre les requêtes d’un même utilisateur (panier, préférences, tunnel), stocké côté serveur et référencé par un cookie.
2. Qu’est-ce qu’un message flash ?
Une donnée en session éphémère, lue une seule fois (à la requête suivante, typiquement après une redirection) puis supprimée — idéale pour les messages de confirmation.
3. Faut-il stocker des entités Doctrine complètes en session ?
Non : préférez des identifiants ou des données minimales, et rechargez les entités depuis la base (éviter sérialisation lourde et données périmées).
4. L’API headless de BookLab utilise-t-elle des sessions ?
Non : elle est stateless (JWT). Les sessions sont réservées au back-office Twig. Le firewall d’API est configuré stateless: true.
5. Où stocke-t-on les sessions en production multi-serveurs ?
Dans un stockage partagé (Redis recommandé, ou base de données), pour éviter qu’un utilisateur perde sa session en changeant de serveur.
Prochain chapitre : 4.6 — Commandes console — créer des commandes bin/console, arguments/options, sortie stylée : l’autre porte d’entrée de votre application.