Licence CC BY-NC-SA

Personnaliser les pages d'erreur

Avec Symfony2, lorsqu'une exception est déclenchée, le noyau l'attrape. Cela lui permet ensuite d'effectuer l'action adéquate.

Le comportement par défaut du noyau consiste à appeler un contrôleur particulier intégré à Symfony2 : TwigBundle:Exception:show. Ce contrôleur récupère les informations de l'exception, choisit le template adéquat (un template différent par type d'erreur : 404, 500, etc.), passe les informations au template et envoie la réponse générée.

À partir de là, il est facile de personnaliser ce comportement : TwigBundle étant… un bundle, on peut le modifier pour l'adapter à nos besoins ! Mais ce n'est pas le comportement que nous voulons changer, c'est juste l'apparence de nos pages d'erreur. Il suffit donc de créer nos propres templates et de dire à Symfony2 d'utiliser nos templates et non ceux par défaut.

Théorie : remplacer les vues d'un bundle

Constater les pages d'erreur

Les pages d'erreur de Symfony2 sont affichées lorsque le noyau attrape une exception. Il existe deux pages différentes : celle en mode dev et celle en mode prod.

Il est possible de personnaliser les deux, mais celle qui nous intéresse le plus ici est la page d'erreur en mode production. En effet, c'est celle qui sera affichée à nos visiteurs ; elle mérite donc toute notre attention.

Je vous invite donc à vous remémorer ce à quoi elle ressemble. Pour cela, accédez à une URL inexistante via app.php, et voyez le résultat à la figure suivante.

Une page d'erreur pas très séduisante

Comme vous pouvez le constater, ce n'est pas très présentable pour nos futurs visiteurs !

Localiser les vues concernées

Avant de chercher à modifier des vues, il faut d'abord bien les identifier. Comme je vous l'ai précisé, les vues de ces pages d'erreur se situent dans le bundle TwigBundle, et plus précisément dans le répertoire vendor\symfony\symfony\src\Symfony\Bundle\TwigBundle\Resources\views\Exception.

Je vous donne leur localisation pour information, mais n'allez surtout pas modifier directement les fichiers de ce répertoire ! Comme tout ce qui se situe dans le répertoire vendor, ils sont susceptibles d'être écrasés par Composer à la prochaine mise à jour.

Remplacer les vues d'un bundle

Il est très simple de remplacer les vues d'un bundle quelconque par les nôtres. Il suffit de créer le répertoire app/Resources/NomDuBundle/views/ et d'y placer nos vues à nous ! Et cela est valable quelque soit le bundle.

Nos vues doivent porter exactement les mêmes noms que celles qu'elles remplacent. Ainsi, si notre bundle utilise une vue située dans :

1
…(namespace)/RépertoireDuBundle/Resources/views/Hello/salut.html.twig

alors nous devons créer la vue :

1
app/Resources/NomDuBundle/views/Hello/salut.html.twig

Attention, NomDuBundle correspond bien au nom du bundle, à savoir au nom du fichier que vous pouvez trouver à sa racine. Par exemple : SdzBlogBundle est le nom du bundle, mais il se trouve dans (src)/Sdz/BlogBundle.

La figure suivante présente un schéma pour bien comprendre, appliqué à la vue error.html.twig du bundle TwigBundle.

Syntaxe pour remplacer une vue

Comportement de Twig

Twig, pour chaque vue qu'on lui demande de retourner, regarde d'abord dans le répertoire app/Resources s'il trouve la vue correspondante. S'il ne la trouve pas, il va ensuite voir dans le répertoire du bundle.

Ainsi, ici pour chaque TwigBundle:Exception:error.html.twig, Twig ira vérifier dans le répertoire app avant de prendre la vue du bundle TwigBundle.

Attention, ceci n'est valable que pour les vues, car c'est le comportement de Twig. Cela ne fonctionne pas pareil pour tout ce qui est contrôleur et autres !

Pourquoi il y a tous les formats error.XXX.twig dans le répertoire Exception ?

C'est une très bonne question, et si vous les ouvrez vous vous rendrez compte que chaque vue d'erreur est compatible au format de son extension. Cela permet de ne pas générer des erreurs en cascade.

Je m'explique, imaginons que vous chargiez un fichier JS, généré dynamiquement par l'un de vos contrôleurs (pourquoi pas !). Si ce contrôleur génère une erreur quelconque, et qu'il affiche cette erreur en HTML, alors votre navigateur qui attend du JavaScript sera perdu ! Il va tenter d'exécuter le retour du contrôleur en tant que JavaScript, mais le retour est en réalité du HTML et générera donc pas mal d'erreurs dans votre navigateur.

C'est pour éviter ce comportement que Symfony2 fournit plusieurs formats d'erreur. Ainsi, si le format de votre réponse est défini comme du JavaScript, alors Symfony2 utilisera la vue error.js.twig qui est, si vous l'ouvrez, compatible JavaScript car en commentaire. Vous remercierez Symfony2 la prochaine fois que cela vous arrivera !

Pratique : remplacer les templates Exception de TwigBundle

Créer la nouvelle vue

Maintenant qu'on sait le faire, il ne reste plus qu'à le faire ! Créez donc le répertoire app/Resources/TwigBundle/views/Exception. Et au sein de ce répertoire, le bundle utilise la convention suivante pour chaque nom de template :

  • Il vérifie d'abord l'existence de la vue error[code_erreur].html.twig, par exemple error404.html.twig dans le cas d'une page introuvable (erreur 404) ;
  • Si ce template n'existe pas, il utilise la vue error.html.twig, une sorte de page d'erreur générique.

Je vous conseille de créer un error404.html.twig pour les pages non trouvées, en plus du error.html.twig générique. Cela vous permet d'afficher un petit texte sympa pour que l'utilisateur ne soit pas trop perdu.

Le contenu d'une page d'erreur

Pour savoir quoi mettre dans ces vues, je vous propose de jeter un œil à celle qui existe déjà, error.html. Vous la trouvez comme indiqué plus haut dans le répertoire vendor\symfony\src\Symfony\Bundle\TwigBundle\Resources\views\Exception, voici son contenu :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>An Error Occurred: {{ status_text }}</title>
  </head>
  <body>
    <h1>Oops! An Error Occurred</h1>
    <h2>The server returned a "{{ status_code }} {{ status_text }}".</h2>

    <div>
      Something is broken. Please e-mail us at [email] and let us know
      what you were doing when this error occurred. We will fix it as soon
      as possible. Sorry for any inconvenience caused.
    </div>
  </body>
</html>

Vous pouvez y voir les différentes variables que vous pouvez utiliser : {{ status_text }} et {{ status_code }}. Fort de cela, vous pouvez créer la page d'erreur que vous souhaitez : vous avez toutes les clés.

Je le rappelle : cette page d'erreur que l'on vient de personnaliser, c'est la page d'erreur générée en mode prod !

Remplacer la page d'erreur du mode dev n'a pas beaucoup d'intérêt : vous seuls la voyez, et elle est déjà très complète. Cependant, si vous souhaitez quand même la modifier, alors cela n'est pas le template error.html.twig qu'il faut créer, mais le template exception.html.twig. Celui-ci se trouve aussi dans le répertoire Exception.


En résumé

  • Modifier les vues d'un bundle quelconque est très pratique, votre site garde ainsi une cohérence dans son design, et ce, que ce soit sur votre bundle à vous comme sur les autres ;
  • Personnaliser les pages d'erreur, ce n'est pas la priorité lorsque l'on démarre un projet Symfony2, mais c'est impératif avant de l'ouvrir à nos visiteurs.