【问题标题】:Catch different Exception types捕获不同的异常类型
【发布时间】:2018-01-04 11:08:12
【问题描述】:

我有一个非常简单的函数来检查一个实体是否存在于一个包中:

public function checkExists($bundle, $val)
{
    try{
       $this->em->getRepository($bundle.':'.$val);
    }catch (MappingException $e){
        return false;
    }

    return true;
}

所以我有以下几种情况:

Input                        |    Expected    |    Actual
'AppBundle', 'Company'       |    true        |    true
'AppBundle', 'NONEXISTANT'   |    false       |    false (MappingException caught)
'NONEXISTANT', 'Company'     |    false       |    500 (ORMException not caught)
'NONEXISTANT', 'NONEXISTANT' |    false       |    500 (ORMException not caught)

所以我看到问题是抛出了不同的异常,但是对于一个部分不存在的任何一种情况,我怎么能返回 false 呢?在 symfony 中是否有一种“通用”方法来捕获异常,因为 catch (Exception $e)use Symfony\Component\Config\Definition\Exception\Exception; 无法捕获它。

【问题讨论】:

标签: php symfony exception-handling try-catch


【解决方案1】:

有几件事要做: 您可以先捕获所有异常,然后可以对每个异常进行不同的处理:

public function checkExists($bundle, $val)
{
    try{
       $this->em->getRepository($bundle.':'.$val);
    } catch (\Exception $e){ // \Exception  is the global scope exception
        if ($e instanceof MappingException || $e instanceof ORMException) {
            return false;
        } 
        throw $e; //Rethrow it if you can't handle it here.
    }

    return true;
}

交替有多个捕获:

 public function checkExists($bundle, $val)
{
    try{
       $this->em->getRepository($bundle.':'.$val);
    } catch (MappingException $e){
       return false;
    } catch (ORMException $e) {
       return false;
    }  //Other exceptions are still unhandled.

    return true;
}

如果您使用的是 PHP 7.1 +,那么您也可以这样做:

public function checkExists($bundle, $val)
{
    try{
       $this->em->getRepository($bundle.':'.$val);
    } catch (MappingException | ORMException $e){ //Catch either MappingException or ORMException 
       return false;
    }  //Other exceptions are still unhandled.

    return true;
}

【讨论】:

    【解决方案2】:

    创建异常监听器并在那里处理它们。

    class ExceptionListener
    {
        /** @var LoggerInterface */
        private $logger;
    
        public function __construct(LoggerInterface $logger)
        {
            $this->logger = $logger;
        }
    
        public function onKernelException(GetResponseForExceptionEvent $event)
        {
            $e = $event->getException();
            if ($e instanceof ValidationException) {
                $this->logger->notice('Validation error' , $e->getViolations());
            } elseif ($e instanceof DomainException) {
                $this->logger->warning('Exception ' . get_class($e) , ['message' => $e->getMessage()]);
                $event->setResponse(
                new JsonResponse(['error' => $this->translator->trans($e->getOutMessage())], 400)
                );
            } else {
                $event->setResponse(
                    new JsonResponse(['error' => $this->translator->trans('http.internal_server_error')], 500)
                );
            }
        }
    }
    

    更新 services.yml

      app.exception_listener:
        class: Application\Listeners\ExceptionListener
        arguments: ['@domain.logger']
        tags:
          - { name: kernel.event_listener, event: kernel.exception }
    

    进一步阅读关于监听器和事件https://symfony.com/doc/current/event_dispatcher.html

    我不确定您是否应该在您的应用程序交付时创建引发映射异常的情况。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-08
      • 2015-11-17
      相关资源
      最近更新 更多