
Rediriger après soumission et afficher un message flash
Découvrez l'importance du pattern Post/Redirect/Get (PRG) dans Symfony et comment utiliser `redirectToRoute` pour rediriger après la soumission d'un formulaire, ainsi que `addFlash` pour afficher des messages de notification.
Le pattern Post/Redirect/Get (PRG) : Pourquoi est-ce crucial ?
Lorsqu'un utilisateur soumet un formulaire via une requête HTTP POST, si le serveur répond directement avec une page HTML (la page de confirmation, par exemple), un problème courant survient : si l'utilisateur actualise cette page de confirmation (avec F5 ou le bouton d'actualisation du navigateur), le navigateur va généralement proposer de renvoyer les mêmes données POST. Cela peut entraîner des soumissions multiples non désirées (par exemple, créer plusieurs fois le même article de blog, effectuer plusieurs fois le même paiement, etc.). De plus, l'URL affichée dans le navigateur reste celle de l'action POST, ce qui n'est pas idéal pour les marque-pages ou le partage de liens.
Le pattern Post/Redirect/Get (PRG) résout ce problème élégamment. Le flux est le suivant :
- L'utilisateur soumet le formulaire (requête POST).
- Le serveur traite les données du formulaire.
- Au lieu de retourner directement une page HTML, le serveur répond avec une redirection HTTP (code de statut 302 ou 303) vers une autre URL (la page de succès ou de visualisation).
- Le navigateur de l'utilisateur suit cette redirection en effectuant une nouvelle requête GET vers cette nouvelle URL.
- Le serveur répond à cette requête GET avec la page HTML finale.
Ainsi, la dernière interaction du navigateur avec le serveur est une requête GET. Si l'utilisateur actualise cette page, il actualisera la requête GET, ce qui est généralement sans effet de bord indésirable. L'URL affichée est également propre et partageable. C'est une pratique standard et fortement recommandée dans le développement web.
Mise en oeuvre de la redirection avec `redirectToRoute()` dans Symfony
Dans Symfony, la redirection après le traitement réussi d'un formulaire est facilitée par la méthode redirectToRoute() disponible dans les contrôleurs qui étendent AbstractController. Cette méthode prend en premier argument le nom de la route vers laquelle vous souhaitez rediriger, et en second argument optionnel un tableau de paramètres pour cette route (si elle en nécessite).
Reprenons notre exemple de la méthode newTask() dans TaskController. Après avoir traité les données du formulaire soumis et valide (même si c'est une simulation pour l'instant), nous voulons rediriger l'utilisateur, par exemple vers la liste des tâches simulées ou la liste principale.
// Dans src/Controller/TaskController.php
// ... (imports et début de la classe TaskController)
#[Route('/tache/nouvelle', name: 'app_task_create', methods: ['GET', 'POST'])]
public function newTask(Request $request): Response
{
$taskData = [];
$form = $this->createForm(TaskType::class, $taskData);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$submittedData = $form->getData();
// Simulation d'ajout à notre 'fausse' base de données
$newId = count(self::$simulatedTasksStorage) > 0 ? max(array_column(self::$simulatedTasksStorage, 'id')) + 1 : 1;
$newTaskEntry = [
'id' => $newId,
'title' => $submittedData['title'],
'description' => $submittedData['description'],
'completed' => false,
];
self::$simulatedTasksStorage[] = $newTaskEntry;
// Ajout d'un message flash (voir section suivante)
$this->addFlash(
'success', // Type de message
sprintf('La tâche "%s" a été ajoutée avec succès (simulation ID: %d)!', $submittedData['title'], $newId)
);
// Redirection vers la liste des tâches simulées
return $this->redirectToRoute('app_task_simulated_list');
// Alternative: Rediriger vers la page de détail de la tâche nouvellement créée (si elle avait une route)
// return $this->redirectToRoute('app_task_show_simulated', ['id' => $newId]);
// (en supposant qu'une telle route 'app_task_show_simulated' existe)
}
return $this->render('task/new.html.twig', [
'taskForm' => $form->createView(),
]);
}L'appel à return $this->redirectToRoute('app_task_simulated_list'); génère un objet RedirectResponse qui instruit le navigateur de l'utilisateur de faire une nouvelle requête GET vers l'URL associée à la route nommée app_task_simulated_list. C'est simple, clair et respecte le pattern PRG.
Utilisation des messages flash pour les notifications utilisateur
Lorsqu'on redirige un utilisateur après une action, il est souvent nécessaire de lui fournir un retour d'information sur le résultat de cette action (par exemple, "Votre tâche a été enregistrée avec succès" ou "Une erreur s'est produite"). Cependant, comme la redirection implique une nouvelle requête, nous ne pouvons pas simplement passer une variable au template de la page de destination de la manière habituelle. C'est là qu interviennent les messages flash.
Les messages flash sont des messages stockés dans la session de l'utilisateur et qui sont destinés à être affichés une seule fois. Après avoir été affichés, ils sont automatiquement supprimés de la session. Symfony rend leur utilisation très aisée grâce à la méthode addFlash() disponible dans AbstractController.
La méthode addFlash() prend deux arguments :
$type(string) : Un type ou une catégorie pour le message (par exemple,'success','error','info','warning'). Ce type peut être utilisé dans le template pour styliser le message différemment.$message(string) : Le contenu du message à afficher.
Dans notre exemple précédent, nous avons utilisé $this->addFlash('success', sprintf(...)); juste avant la redirection. Ce message sera disponible dans le template de la page vers laquelle nous redirigeons (app_task_simulated_list dans notre cas).
Affichage des messages flash dans les templates Twig
Pour que les messages flash soient effectivement visibles par l'utilisateur, vous devez ajouter une petite section de code dans vos templates Twig, généralement dans votre template de base (layout) afin qu'ils puissent s'afficher sur n'importe quelle page après une redirection. Twig accède aux messages flash via la variable globale app.flashes.
app.flashes est un tableau où chaque clé est un type de message (celui que vous avez défini avec addFlash()) et chaque valeur est un tableau des messages de ce type (car vous pouvez ajouter plusieurs messages du même type). Voici comment les afficher, par exemple dans templates/base.html.twig, juste après l'ouverture de la balise :
{# Extrait de templates/base.html.twig #}
&t;body>
{# Section pour afficher les messages flash #}
{% if app.flashes is not empty %}
&t;div class="container mt-3"> {# Pour un meilleur style avec Bootstrap #}
{% for type, messages in app.flashes %}
{% for message in messages %}
&t;div class="alert alert-{{ type }} alert-dismissible fade show" role="alert">
{{ message|raw }} {# Utiliser 'raw' si le message contient du HTML, sinon simple {{ message }} #}
&t;button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close">&t;/button>
&t;/div>
{% endfor %}
{% endfor %}
&t;/div>
{% endif %}
&t;nav>...&t;/nav>
&t;main role="main" class="container">
{% block body %}{% endblock %}
&t;/main>
&t;footer>...&t;/footer>
{% block javascripts %}
{# ... vos scripts ... #}
{# Pour que le bouton de fermeture des alertes Bootstrap fonctionne #}
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
{% endblock %}
&t;/body>Ce code parcourt tous les types de messages flash disponibles. Pour chaque type, il parcourt tous les messages et les affiche dans un En combinant la redirection avec alert-success pour les messages de type 'success'). L'exemple utilise des classes Bootstrap pour un affichage agréable et une fonctionnalité de fermeture de l'alerte.redirectToRoute() et les notifications utilisateur via addFlash(), vous créez une expérience utilisateur professionnelle, robuste et conforme aux bonnes pratiques du web.