Skip to content

Example of handling exceptions with listeners #5503

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 121 additions & 0 deletions cookbook/controller/error_pages.rst
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,127 @@ This approach allows you to create centralized and layered error handling:
instead of catching (and handling) the same exceptions in various controllers
time and again, you can have just one (or several) listeners deal with them.

A centralized error handling that also allows to log exceptions might look like this::

// src/AppBundle/EventListener/ExceptionListener.php
namespace AppBundle\EventListener;

use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;

class ExceptionListener
{
private $logger;

public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}

public function onKernelException(GetResponseForExceptionEvent $event)
{
// Get the exception object from the received event
$exception = $event->getException();
$message = sprintf(
'Error: %s. Code: %s',
$exception->getMessage(),
$exception->getCode()
);

// Log the exception to the configured log file (i.e. app.log)
$this->logger->error($message);

// Customize the response object to display the exception details
$response = new Response();
$response->setContent($message);

// HttpExceptionInterface is a special type of exception that
// holds status code and header details
if ($exception instanceof HttpExceptionInterface) {
$response->setStatusCode($exception->getStatusCode());
$response->headers->replace($exception->getHeaders());
} else {
$response->setStatusCode(Response::HTTP_INTERNAL_SERVER_ERROR);
}

// Send the modified response object to the event
$event->setResponse($response);
}
}

Now, you need to register your listener:

.. configuration-block::

.. code-block:: yaml

# app/config/services.yml
services:
app.exception_listener:
class: AppBundle\EventListener\ExceptionListener
arguments: ["@logger"]
tags:
- { name: kernel.event_listener, event: kernel.exception, method: onKernelException }

.. code-block:: xml

<!-- app/config/services.xml -->
<service id="app.exception_listener" class="AppBundle\EventListener\ExceptionListener">
<argument type="service" id="logger" />
<tag name="kernel.event_listener" event="kernel.exception" method="onKernelException" />
</service>

.. code-block:: php

// app/config/services.php
$container
->register('app.exception_listener', 'AppBundle\EventListener\ExceptionListener')
->addArgument(new Reference('logger'))
->addTag('kernel.event_listener', array('event' => 'kernel.exception', 'method' => 'onKernelException'))
;

Finally, you need to add a new handler that will log the exceptions to the configured log file (app.log):

.. configuration-block::

.. code-block:: yaml

# app/config/config.yml
monolog:
handlers:
applog:
type: stream
path: /path/to/app.log
level: error

.. code-block:: xml

<!-- app/config/config.xml -->
<monolog:config>
<monolog:handler
name="applog"
type="stream"
path="/path/to/app.log"
level="error"
/>
</monolog:config>
</container>

.. code-block:: php

// app/config/config.php
$container->loadFromExtension('monolog', array(
'handlers' => array(
'applog' => array(
'type' => 'stream',
'path' => '/path/to/app.log',
'level' => 'error',
),
),
));

.. tip::

See :class:`Symfony\\Component\\Security\\Http\\Firewall\\ExceptionListener`
Expand Down