Skip to content

Commit 907ce67

Browse files
committed
Merge branch '2.5'
* 2.5: Improve cookbook entry for error pages in 2.3~
2 parents 3b6d6d6 + d618fd0 commit 907ce67

File tree

1 file changed

+209
-76
lines changed

1 file changed

+209
-76
lines changed

cookbook/controller/error_pages.rst

+209-76
Original file line numberDiff line numberDiff line change
@@ -5,46 +5,100 @@
55
How to Customize Error Pages
66
============================
77

8-
When any exception is thrown in Symfony, the exception is caught inside the
9-
``Kernel`` class and eventually forwarded to a special controller,
10-
``TwigBundle:Exception:show`` for handling. This controller, which lives
11-
inside the core TwigBundle, determines which error template to display and
12-
the status code that should be set for the given exception.
8+
When an exception is thrown, the core ``HttpKernel`` class catches it and
9+
dispatches a ``kernel.exception`` event. This gives you the power to convert
10+
the exception into a ``Response`` in a few different ways.
1311

14-
Error pages can be customized in two different ways, depending on how much
15-
control you need:
12+
The core TwigBundle sets up a listener for this event which will run
13+
a configurable (but otherwise arbitrary) controller to generate the
14+
response. The default controller used has a sensible way of
15+
picking one out of the available set of error templates.
1616

17-
1. Customize the error templates of the different error pages;
17+
Thus, error pages can be customized in different ways, depending on how
18+
much control you need:
1819

19-
2. Replace the default exception controller ``twig.controller.exception:showAction``.
20+
#. :ref:`Use the default ExceptionController and create a few
21+
templates that allow you to customize how your different error
22+
pages look (easy); <use-default-exception-controller>`
2023

21-
The default ExceptionController
22-
-------------------------------
24+
#. :ref:`Replace the default exception controller with your own
25+
(intermediate). <custom-exception-controller>`
2326

24-
The default ``ExceptionController`` will either display an
27+
#. :ref:`Use the kernel.exception event to come up with your own
28+
handling (advanced). <use-kernel-exception-event>`
29+
30+
.. _use-default-exception-controller:
31+
32+
Using the Default ExceptionController
33+
-------------------------------------
34+
35+
By default, the ``showAction()`` method of the
36+
:class:`Symfony\\Bundle\\TwigBundle\\Controller\\ExceptionController`
37+
will be called when an exception occurs.
38+
39+
This controller will either display an
2540
*exception* or *error* page, depending on the setting of the ``kernel.debug``
2641
flag. While *exception* pages give you a lot of helpful
2742
information during development, *error* pages are meant to be
28-
shown to the end-user.
43+
shown to the user in production.
2944

3045
.. sidebar:: Testing Error Pages during Development
3146

3247
You should not set ``kernel.debug`` to ``false`` in order to see your
33-
error pages during development. This will also stop
48+
*error* pages during development. This will also stop
3449
Symfony from recompiling your twig templates, among other things.
3550

3651
The third-party `WebfactoryExceptionsBundle`_ provides a special
3752
test controller that allows you to display your custom error
3853
pages for arbitrary HTTP status codes even with
3954
``kernel.debug`` set to ``true``.
4055

41-
Override Error Templates
42-
------------------------
56+
.. _`WebfactoryExceptionsBundle`: https://github.com/webfactory/exceptions-bundle
57+
58+
.. _cookbook-error-pages-by-status-code:
59+
60+
How the Template for the Error and Exception Pages Is Selected
61+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4362

44-
All of the error templates live inside the TwigBundle. To override the
45-
templates, simply rely on the standard method for overriding templates that
46-
live inside a bundle. For more information, see
47-
:ref:`overriding-bundle-templates`.
63+
The TwigBundle contains some default templates for error and
64+
exception pages in its ``Resources/views/Exception`` directory.
65+
66+
.. tip::
67+
68+
In a standard Symfony installation, the TwigBundle can be found at
69+
``vendor/symfony/symfony/src/Symfony/Bundle/TwigBundle``. In addition
70+
to the standard HTML error page, it also provides a default
71+
error page for many of the most common response formats, including
72+
JSON (``error.json.twig``), XML (``error.xml.twig``) and even
73+
JavaScript (``error.js.twig``), to name a few.
74+
75+
Here is how the ``ExceptionController`` will pick one of the
76+
available templates based on the HTTP status code and request format:
77+
78+
* For *error* pages, it first looks for a template for the given format
79+
and status code (like ``error404.json.twig``);
80+
81+
* If that does not exist or apply, it looks for a general template for
82+
the given format (like ``error.json.twig`` or
83+
``exception.json.twig``);
84+
85+
* Finally, it ignores the format and falls back to the HTML template
86+
(like ``error.html.twig`` or ``exception.html.twig``).
87+
88+
.. tip::
89+
90+
If the exception being handled implements the
91+
:class:`Symfony\\Component\\HttpKernel\\Exception\\HttpExceptionInterface`,
92+
the ``getStatusCode()`` method will be
93+
called to obtain the HTTP status code to use. Otherwise,
94+
the status code will be "500".
95+
96+
Overriding or Adding Templates
97+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
98+
99+
To override these templates, simply rely on the standard method for
100+
overriding templates that live inside a bundle. For more information,
101+
see :ref:`overriding-bundle-templates`.
48102

49103
For example, to override the default error template, create a new
50104
template located at
@@ -74,82 +128,161 @@ template located at
74128

75129
.. tip::
76130

77-
If you're not familiar with Twig, don't worry. Twig is a simple, powerful
78-
and optional templating engine that integrates with Symfony. For more
79-
information about Twig see :doc:`/book/templating`.
131+
If you're not familiar with Twig, don't worry. Twig is a simple,
132+
powerful and optional templating engine that integrates with
133+
Symfony. For more information about Twig see :doc:`/book/templating`.
80134

81-
In addition to the standard HTML error page, Symfony provides a default error
82-
page for many of the most common response formats, including JSON
83-
(``error.json.twig``), XML (``error.xml.twig``) and even JavaScript
84-
(``error.js.twig``), to name a few. To override any of these templates, just
85-
create a new file with the same name in the
86-
``app/Resources/TwigBundle/views/Exception`` directory. This is the standard
87-
way of overriding any template that lives inside a bundle.
135+
This works not only to replace the default templates, but also to add
136+
new ones.
88137

89-
.. _cookbook-error-pages-by-status-code:
138+
For instance, create an ``app/Resources/TwigBundle/views/Exception/error404.html.twig``
139+
template to display a special page for 404 (page not found) errors.
140+
Refer to the previous section for the order in which the
141+
``ExceptionController`` tries different template names.
90142

91-
Customizing the 404 Page and other Error Pages
92-
----------------------------------------------
143+
.. tip::
93144

94-
You can also customize specific error templates according to the HTTP status
95-
code. For instance, create a
96-
``app/Resources/TwigBundle/views/Exception/error404.html.twig`` template to
97-
display a special page for 404 (page not found) errors.
145+
Often, the easiest way to customize an error page is to copy it from
146+
the TwigBundle into ``app/Resources/TwigBundle/views/Exception`` and
147+
then modify it.
98148

99-
Symfony uses the following algorithm to determine which template to use:
149+
.. note::
100150

101-
* First, it looks for a template for the given format and status code (like
102-
``error404.json.twig``);
151+
The debug-friendly exception pages shown to the developer can even be
152+
customized in the same way by creating templates such as
153+
``exception.html.twig`` for the standard HTML exception page or
154+
``exception.json.twig`` for the JSON exception page.
155+
156+
.. _custom-exception-controller:
103157

104-
* If it does not exist, it looks for a template for the given format (like
105-
``error.json.twig``);
158+
Replacing the Default ExceptionController
159+
------------------------------------------
160+
161+
If you need a little more flexibility beyond just overriding the
162+
template, then you can change the controller that renders the error
163+
page. For example, you might need to pass some additional variables into
164+
your template.
165+
166+
.. caution::
106167

107-
* If it does not exist, it falls back to the HTML template (like
108-
``error.html.twig``).
168+
Make sure you don't lose the exception pages that render the helpful
169+
error messages during development.
170+
171+
To do this, simply create a new controller and set the
172+
:ref:`twig.exception_controller <config-twig-exception-controller>` option
173+
to point to it.
174+
175+
.. configuration-block::
176+
177+
.. code-block:: yaml
178+
179+
# app/config/config.yml
180+
twig:
181+
exception_controller: AcmeFooBundle:Exception:showException
182+
183+
.. code-block:: xml
184+
185+
<!-- app/config/config.xml -->
186+
<?xml version="1.0" encoding="UTF-8" ?>
187+
<container xmlns="http://symfony.com/schema/dic/services"
188+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
189+
xmlns:twig="http://symfony.com/schema/dic/twig"
190+
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
191+
http://symfony.com/schema/dic/twig http://symfony.com/schema/dic/twig/twig-1.0.xsd">
192+
193+
<twig:config>
194+
<twig:exception-controller>AcmeFooBundle:Exception:showException</twig:exception-controller>
195+
</twig:config>
196+
</container>
197+
198+
.. code-block:: php
199+
200+
// app/config/config.php
201+
$container->loadFromExtension('twig', array(
202+
'exception_controller' => 'AcmeFooBundle:Exception:showException',
203+
// ...
204+
));
109205
110206
.. tip::
111207

112-
To see the full list of default error templates, see the
113-
``Resources/views/Exception`` directory of the TwigBundle. In a
114-
standard Symfony installation, the TwigBundle can be found at
115-
``vendor/symfony/symfony/src/Symfony/Bundle/TwigBundle``. Often, the easiest way
116-
to customize an error page is to copy it from the TwigBundle into
117-
``app/Resources/TwigBundle/views/Exception`` and then modify it.
208+
You can also set up your controller as a service.
118209

119-
.. note::
210+
The default value of ``twig.controller.exception:showAction`` refers
211+
to the ``showAction`` method of the ``ExceptionController``
212+
described previously, which is registered in the DIC as the
213+
``twig.controller.exception`` service.
120214

121-
The debug-friendly exception pages shown to the developer can even be
122-
customized in the same way by creating templates such as
123-
``exception.html.twig`` for the standard HTML exception page or
124-
``exception.json.twig`` for the JSON exception page.
215+
Your controller will be passed two parameters: ``exception``,
216+
which is a :class:`\\Symfony\\Component\\Debug\\Exception\\FlattenException`
217+
instance created from the exception being handled, and ``logger``,
218+
an instance of :class:`\\Symfony\\Component\\HttpKernel\\Log\\DebugLoggerInterface`
219+
(which may be ``null``).
125220

126-
.. _`WebfactoryExceptionsBundle`: https://github.com/webfactory/exceptions-bundle
221+
.. tip::
127222

128-
Replace the default Exception Controller
129-
----------------------------------------
223+
The Request that will be dispatched to your controller is created
224+
in the :class:`Symfony\\Component\\HttpKernel\\EventListener\\ExceptionListener`.
225+
This event listener is set up by the TwigBundle.
130226

131-
If you need a little more flexibility beyond just overriding the template
132-
(e.g. you need to pass some additional variables into your template),
133-
then you can override the controller that renders the error page.
227+
You can, of course, also extend the previously described
228+
:class:`Symfony\\Bundle\\TwigBundle\\Controller\\ExceptionController`.
229+
In that case, you might want to override one or both of the
230+
``showAction`` and ``findTemplate`` methods. The latter one locates the
231+
template to be used.
134232

135-
The default exception controller is registered as a service - the actual
136-
class is ``Symfony\Bundle\TwigBundle\Controller\ExceptionController``.
233+
.. caution::
137234

138-
To do this, create a new controller class and make it extend Symfony's default
139-
``Symfony\Bundle\TwigBundle\Controller\ExceptionController`` class.
235+
As of writing, the ``ExceptionController`` is *not* part of the
236+
Symfony API, so be aware that it might change in following releases.
140237

141-
There are several methods you can override to customize different parts of how
142-
the error page is rendered. You could, for example, override the entire
143-
``showAction`` or just the ``findTemplate`` method, which locates which
144-
template should be rendered.
238+
.. _use-kernel-exception-event:
145239

146-
To make Symfony use your exception controller instead of the default, set the
147-
:ref:`twig.exception_controller <config-twig-exception-controller>` option
148-
in app/config/config.yml.
240+
Working with the kernel.exception Event
241+
-----------------------------------------
242+
243+
As mentioned in the beginning, the ``kernel.exception`` event is
244+
dispatched whenever the Symfony Kernel needs to
245+
handle an exception. For more information on that, see :ref:`kernel-kernel.exception`.
246+
247+
Working with this event is actually much more powerful than what has
248+
been explained before but also requires a thorough understanding of
249+
Symfony internals.
250+
251+
To give one example, assume your application throws
252+
specialized exceptions with a particular meaning to your domain.
253+
254+
In that case, all the default ``ExceptionListener`` and
255+
``ExceptionController`` could do for you was trying to figure out the
256+
right HTTP status code and display your nice-looking error page.
257+
258+
:doc:`Writing your own event listener </cookbook/service_container/event_listener>`
259+
for the ``kernel.exception`` event allows you to have a closer look
260+
at the exception and take different actions depending on it. Those
261+
actions might include logging the exception, redirecting the user to
262+
another page or rendering specialized error pages.
263+
264+
.. note::
265+
266+
If your listener calls ``setResponse()`` on the
267+
:class:`Symfony\\Component\\HttpKernel\\Event\\GetResponseForExceptionEvent`,
268+
event propagation will be stopped and the response will be sent to
269+
the client.
270+
271+
This approach allows you to create centralized and layered error
272+
handling: Instead of catching (and handling) the same exceptions
273+
in various controllers again and again, you can have just one (or
274+
several) listeners deal with them.
149275

150276
.. tip::
151277

152-
The customization of exception handling is actually much more powerful
153-
than what's written here. An internal event, ``kernel.exception``, is thrown
154-
which allows complete control over exception handling. For more
155-
information, see :ref:`kernel-kernel.exception`.
278+
To see an example, have a look at the `ExceptionListener`_ in the
279+
Security Component.
280+
281+
It handles various security-related exceptions that are thrown in
282+
your application (like :class:`Symfony\\Component\\Security\\Core\\Exception\\AccessDeniedException`)
283+
and takes measures like redirecting the user to the login page,
284+
logging them out and other things.
285+
286+
Good luck!
287+
288+
.. _`ExceptionListener`: https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php

0 commit comments

Comments
 (0)