2017-04-14 6 views
1

예외 처리를위한 수신기를 만듭니다. 다음은 내 코드 I 생산 모드에서 치명적인 예외를 할 필요가 추가로 어떤 작업 services.ymlSymfony2 커널 예외 이벤트가 프로덕션 모드에서 치명적인 오류 예외를 처리하지 않음

kernel.listener.prod_exception_listener: 
    class: MyBundle\Listener\ExceptionListener 
    tags: 
     - { name: kernel.event_listener, event: kernel.exception, method: onKernelException } 

ExceptionListener.php

<?php 
namespace MyBundle\Listener; 

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

class ExceptionListener 
{ 
    public function onKernelException(GetResponseForExceptionEvent $event) 
    { 
     // no fatal exception goes here others are coming in this function 
     // like 403,404,500 are coming in this block 

    } 
} 

입니까? 왜냐하면 dev 모드에서는 치명적인 오류가 청취자에 들어 오기 때문입니다.

답변

0

나는

api_exception_subscriber: 
    class: AppBundle\EventListener\ApiExceptionSubscriber 
    arguments: ['%kernel.debug%', '@api.response_factory', '@logger'] 
    tags: 
     - { name: kernel.event_subscriber } 
api.response_factory: 
    class: AppBundle\Api\ResponseFactory 

내 응답 공장처럼 내 services.yml에에게 다음과 같은 방법으로, 해결 :

<?php 

namespace AppBundle\Api; 

use Symfony\Component\HttpFoundation\JsonResponse; 

class ResponseFactory 
{ 
    public function createResponse(ApiProblem $apiProblem) 
    { 
     $data = $apiProblem->toArray(); 

     $response = new JsonResponse(
      $data, 
      $apiProblem->getStatusCode() 
     ); 
     $response->headers->set('Content-Type', 'application/json'); 

     return $response; 
    } 
} 

과 API를 subscriper 클래스

<?php 

namespace AppBundle\EventListener; 

use AppBundle\Api\ApiProblem; 
use AppBundle\Api\ApiProblemException; 
use AppBundle\Api\ResponseFactory; 
use Psr\Log\LoggerInterface; 
use Symfony\Component\EventDispatcher\EventSubscriberInterface; 
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; 
use Symfony\Component\HttpKernel\KernelEvents; 
use Symfony\Component\HttpFoundation\JsonResponse; 
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; 

class ApiExceptionSubscriber implements EventSubscriberInterface 
{ 
    private $debug; 

    private $responseFactory; 

    private $logger; 

    public function __construct($debug, ResponseFactory $responseFactory, LoggerInterface $logger) 
    { 
     $this->debug = $debug; 
     $this->responseFactory = $responseFactory; 
     $this->logger = $logger; 
    } 

    public function onKernelException(GetResponseForExceptionEvent $event) 
    { 
     // only reply to /api URLs 
     if (strpos($event->getRequest()->getPathInfo(), '/api') !== 0) { 
      return; 
     } 

     $e = $event->getException(); 

     $statusCode = $e instanceof HttpExceptionInterface ? $e->getStatusCode() : 500; 

     // allow 500 errors to be thrown 
     if ($this->debug && $statusCode >= 500) { 
      return; 
     } 

     $this->logException($e); 

     if ($e instanceof ApiProblemException) { 
      $apiProblem = $e->getApiProblem(); 
     } else { 


      $apiProblem = new ApiProblem(
       $statusCode 
      ); 

      /* 
      * If it's an HttpException message (e.g. for 404, 403), 
      * we'll say as a rule that the exception message is safe 
      * for the client. Otherwise, it could be some sensitive 
      * low-level exception, which should *not* be exposed 
      */ 
      if ($e instanceof HttpExceptionInterface) { 
       $apiProblem->set('detail', $e->getMessage()); 
      } 
     } 

     $response = $this->responseFactory->createResponse($apiProblem); 

     $event->setResponse($response); 
    } 

    public static function getSubscribedEvents() 
    { 
     return array(
      KernelEvents::EXCEPTION => 'onKernelException' 
     ); 
    } 

    /** 
    * Adapted from the core Symfony exception handling in ExceptionListener 
    * 
    * @param \Exception $exception 
    */ 
    private function logException(\Exception $exception) 
    { 
     $message = sprintf('Uncaught PHP Exception %s: "%s" at %s line %s', get_class($exception), $exception->getMessage(), $exception->getFile(), $exception->getLine()); 
     $isCritical = !$exception instanceof HttpExceptionInterface || $exception->getStatusCode() >= 500; 
     $context = array('exception' => $exception); 
     if ($isCritical) { 
      $this->logger->critical($message, $context); 
     } else { 
      $this->logger->error($message, $context); 
     } 
    } 
}