自定义ExceptionListener选择了403& 404,但不是500错误

时间:2014-03-06 12:40:23

标签: symfony

与未回答的问题Symfony 2.4: Why are 500 errors not caught by kernel.exception listener完全相同的问题。

我已经实现了一个自定义异常“处理程序”,它可以很好地处理403和404问题,但有500个错误(这是我真正想要处理的,因为我想在发生这种情况时从系统向自己发送一封电子邮件)不会触发我的自定义“处理程序”并继续表现为好像自定义“处理程序”不在那里。代码相对简单:

从app / config / config.yml中提取:

services:
    core.exceptlistener:
        class: Pmb\LicensingBundle\Listener\ExceptionListener
        arguments:  ["@service_container", "@router"]
        tags:
            - { name: kernel.event_listener, event: kernel.exception, method: onKernelException, priority: 200 }

整个\ Pmb \ LicensingBundle \ Listener \ ExceptionListener.php:

<?php

namespace Pmb\LicensingBundle\Listener;

use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Bundle\TwigBundle\TwigEngine;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

class ExceptionListener
{
    private $container;
    private $router;

    function __construct($container, $router) 
    {
        $this->container = $container;
        $this->router = $router;
    }

    public function onKernelException(GetResponseForExceptionEvent $event)
    {
        $exception = $event->getException();
        die("test");
        $request = $this->container->get('request');
        $templating = $this->container->get('templating');    

        if ($exception instanceof \Symfony\Component\Security\Core\Exception\AccessDeniedException)
        {

            # If AJAX request, do show not error page.
            if ($request->isXmlHttpRequest()) 
            {
                $response = new Response(json_encode(array('error' => 'Access Denied: Not logged in as administrator')));
            }
            else
            {
                return new RedirectResponse($this->router->generate('login'));
            }

            $event->setResponse($response);
        }
        elseif ($exception->getStatusCode() == 404)
        {
            # If AJAX request, do show not error page.
            if ($request->isXmlHttpRequest()) 
            {
                $response = new Response(json_encode(array('error' => 'Requested route could not be found')));
            }
            else
            {
                $response = new Response($templating->render('PmbLicensingBundle:Exception:error404.html.twig', array(
                    'exception' => $exception
                )));
            }

            $event->setResponse($response);
        }       
        else
        {

            # TODO: Send Email
            # If AJAX request, do not show error page.
            if ($request->isXmlHttpRequest()) $response = new Response(json_encode(array('error' => 'Internal Server Error Encountered. Developer has been notified.')));
            else
            {
                $response = new Response($templating->render('PmbLicensingBundle:Exception:error500.html.twig', array(
                    'exception' => $exception
                )));
            }

        }
    }
}

我将die("test")放在那里以验证“处理程序”根本没有被调用,这不仅仅是我的if-else逻辑的问题。如前所述,这适用于任何404或403错误,但500错误完全忽略了这一点,并以默认方式运行。我很确定这与注册侦听器服务有关,但我找不到任何解释如何使其正常工作的内容。

编辑:以下是未按预期处理的错误的屏幕截图。我注意到一个(未定义的变量)die("test");实际显示在底部,但是在ohter(语法错误)上它没有显示,即使它们似乎都被Symfony2捕获。进一步的测试显示die("test");出现了,但是死了(“&gt;&gt;。$ exception-&gt; getStatusCode()。”&lt;&lt;“);没有。我假设这导致了第二次我没有看到的异常,就像AccessDeniedException没有这个函数调用而我必须使用instanceof,但是有很多可能出现500错误的错误,所以如何区分错误是什么是其中之一吗?

enter image description here

enter image description here

enter image description here

进一步编辑:对于在底部打印“测试”的错误,我注意到当我执行$container->testError();时,我没有得到“测试”,错误的底部,但是当我做return $container;时,即使两个错误都是带有未定义变量的ContextErrorException。

2 个答案:

答案 0 :(得分:0)

在Symfony有机会开始之前,你最常得到的500个错误。由于Symfony在这种情况下无法启动,因此无法处理错误。要调试此类情况,您应该查看Web服务器(apache,ngnix等)日志。

答案 1 :(得分:0)

我刚测试了500个例外,它似乎工作正常。我想你可能还有别的事情可以拦截这个例外吗?也许开始一个新项目再试一次。

我自己更喜欢订阅者界面:

class ExceptionListener extends ContainerAware implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return array(KernelEvents::EXCEPTION => array(
            array('doException', 200),
        ));
    }
    public function doException(GetResponseForExceptionEvent $doEvent)
    {
        $exception = $doEvent->getException();

        die('Exception caught ' . $exception->getStatusCode());

cerad_core__exception_listener:
    class:   Cerad\Bundle\CoreBundle\EventListener\ExceptionListener
    tags:
        - { name: kernel.event_subscriber }

请注意,您还可以配置记录器以发送电子邮件。可能会更容易。

http://symfony.com/doc/current/cookbook/logging/monolog_email.html

@Ferhad提出了一个很好的观点。一些(但不是全部)500错误基本上会使S2应用程序崩溃。但我假设您正在获取默认的S2异常消息。