Symfony 2.4: Почему 500 ошибок не перехватываются прослушивателем kernel.exception

Я пытаюсь создать прослушиватель для прослушивания исключений 403, 404 и 500. Это отлично работает для исключений 403 и 404, но не для исключений 500. Для 500 исключений (или исключений, которые будут возвращены клиенту как 500 ошибок) метод onKernelException никогда не вызывается. Похоже, что это то же самое в моем текущем проекте Symfony и когда код добавляется в чистую установку Symfony 2.4.1.

Затем я ввожу ошибку 500, выполняя несуществующую функцию.

В среде разработки я получаю сгенерированную Symfony страницу с надписью «Упс, похоже, что-то пошло не так». а затем просматривает информацию о выброшенном «UndefinedFunctionException» вместе с кодом состояния 500.

В производственной среде я получаю пустую страницу вместе с кодом состояния 500. В журнале ошибок prod.log я получаю сообщение об ошибке «Неустранимая ошибка PHP: вызов неопределенной функции» с трассировкой стека.

Поскольку Symfony, очевидно, ловит эту ошибку, почему я не могу поймать соответствующее исключение с помощью прослушивателя kernel.exception?

Я использую класс:

<?php

namespace SystemBundle\Listener;

use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;

/**
 * This exception listener will listen to 500, 404, and 403 errors and render a corresponding view
 *
 * @SuppressWarnings("static")
 * @SuppressWarnings("else")
 */
class ExceptionListener
{
    protected $templating;
    protected $kernel;

    public function __construct(EngineInterface $templating, $kernel)
    {
        $this->templating = $templating;
        $this->kernel = $kernel;
    }

    public function onKernelException(GetResponseForExceptionEvent $event)
    {
        $container = $this->kernel->getContainer();

        // Exception object
        $exception = $event->getException();

        // Create Response object
        $response = new Response();

        // Get view name
        $viewName = $container->getParameter('theme') . ':Exception:exception.html.twig';
        if (!$this->templating->exists($viewName)) {
            $viewName = 'AckebrinkChallengerSystemBundle:Exception:exception.html.twig';
        }

        // Set response content
        $response->setContent($this->templating->render($viewName, array('exception' => $exception)));

        // 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(500);
        }

        // set the new $response object to the $event
        $event->setResponse($response);
    }
}

и конфигурация службы, которую я использую:

services:
    kernel.listener.system_exception_listener:
        class: SystemBundle\Listener\ExceptionListener
        arguments:
            - @templating
            - @kernel
        tags:
            - { name: kernel.event_listener, event: kernel.exception, method: onKernelException }

person tirithen    schedule 15.01.2014    source источник
comment
Вы используете производственную среду?   -  person Manolo    schedule 15.01.2014
comment
Спасибо, обновите вопрос, чтобы сделать его более понятным, в производственной среде я получаю белую страницу вместе с кодом состояния 500, а в среде разработки я получаю описанное сообщение об ошибке.   -  person tirithen    schedule 15.01.2014
comment
Не могли бы вы повторить переменную $exception, чтобы увидеть, получает ли она значение?   -  person Manolo    schedule 15.01.2014
comment
Нет, я не могу, так как onKernelException не вызывается для 500 ошибок, эти ошибки, похоже, обрабатываются где-то еще. Я обновлю вопрос, чтобы уточнить, что метод никогда не вызывается.   -  person tirithen    schedule 15.01.2014
comment
У меня точно такая же проблема. Ошибки 403 и 404 отлично перехватываются службой listerner, но 500 ошибок обрабатываются, как всегда, полностью игнорируя мой пользовательский класс ExceptionListener.   -  person Magnanimity    schedule 06.03.2014
comment
Зависит от того, где вы вызываете этот несуществующий метод. Будет ли это работать, если вместо этого вы просто вызовете исключение?   -  person thormeier    schedule 20.06.2016


Ответы (2)


Прежде всего, убедитесь, что вы очистили кеш Prod.

Во-вторых, посмотрите, не ловит ли что-то в веб-сервере за вас ошибки, например, fastcgi_intercept_errors в Nginx, но вряд ли это произойдет.

В-третьих, попробуйте создать исключение, а не вызывать необъявленную функцию.

В-четвертых, попробуйте как можно раньше выполнить $event->setResponse в прослушивателе исключений, чтобы убедиться, что в самом обработчике нет ошибки.

Кроме этого, я понятия не имею. Код вроде в порядке. Пробовали ли вы с XDebug посмотреть, как работает код?

person Nico Andrade    schedule 22.06.2016

PHP 7 представил исключения фатальных ошибок. Если вы используете PHP 5.X, приложение останавливается.

person Pierre Emmanuel Lallemant    schedule 22.05.2017