在一个捕获块中捕获多个异常类型

2022-08-30 06:03:47

我想要一种更干净的方式来获得以下功能,以捕获和在一个块中:AErrorBError

try
{
    /* something */
}
catch( AError, BError $e )
{
    handler1( $e )
}
catch( Exception $e )
{
    handler2( $e )
}

有什么办法可以做到这一点吗?还是我必须单独抓住它们?

AError并且有一个共享的基类,但他们也与我想落入的其他类型的类型共享它,所以我不能只抓住基类。Berrorhandler2


答案 1

更新:

从 PHP 7.1 开始,这是可用的。

语法为:

try
{
    // Some code...
}
catch(AError | BError $e)
{
    // Handle exceptions
}
catch(Exception $e)
{
    // Handle the general case
}

文档: https://www.php.net/manual/en/language.exceptions.php#example-294

RFC: https://wiki.php.net/rfc/multiple-catch

提交:https://github.com/php/php-src/commit/0aed2cc2a440e7be17552cc669d71fdd24d1204a


对于 7.1 之前的 PHP:

不管这些其他答案怎么说,你都可以抓住并在同一个块中(如果你是定义异常的人,那就容易一些了)。即使有一些例外你想“掉下来”,你仍然应该能够定义一个层次结构来满足你的需求。AErrorBError

abstract class MyExceptions extends Exception {}

abstract class LetterError extends MyExceptions {}

class AError extends LetterError {}

class BError extends LetterError {}

然后:

catch(LetterError $e){
    //voodoo
}

正如您在此处此处所看到的,即使是默认异常也具有您可以利用的层次结构。此外,如 PHP 手册中所述:SPL

当抛出异常时,语句后面的代码将不会执行,PHP 将尝试查找第一个匹配的 catch 块。

这意味着您也可以拥有

class CError extends LetterError {}

您需要以不同于 或 的方式处理,因此您的 catch 语句将如下所示:AErrorBError

catch(CError $e){
    //voodoo
}
catch(LetterError $e){
    //voodoo
}

如果您遇到过这样的情况:有二十个或更多个例外合法地属于同一超类,并且您需要以一种方式处理其中的五个(或任何大型组),而以另一种方式处理其余的例外,您仍然可以这样做。

interface Group1 {}

class AError extends LetterError implements Group1 {}

class BError extends LetterError implements Group1 {}

然后:

catch (Group1 $e) {}

在异常情况下使用OOP是非常强大的。使用像 或 是黑客,如果可能的话,应该避免使用。get_classinstanceof

我想添加的另一个解决方案是将异常处理功能放在自己的方法中。

你可以有

function handleExceptionMethod1(Exception $e)
{
    //voodoo
}

function handleExceptionMethod2(Exception $e)
{
    //voodoo
}

假设绝对没有办法控制异常类层次结构或接口(几乎总是有办法),你可以执行以下操作:

try
{
    stuff()
}
catch(ExceptionA $e)
{
    $this->handleExceptionMethod1($e);
}
catch(ExceptionB $e)
{
    $this->handleExceptionMethod1($e);
}
catch(ExceptionC $e)
{
    $this->handleExceptionMethod1($e);
}
catch(Exception $e)
{
    $this->handleExceptionMethod2($e);
}

这样,如果您的异常处理机制需要更改,您仍然只有一个代码位置需要修改,并且您是在 OOP 的一般构造中工作的。


答案 2

在 PHP >= 7.1 中,这是可能的。看到这个答案


如果可以修改例外,请使用此答案

如果不能,可以尝试捕获所有异常,然后检查使用 instanceof 引发的异常。Exception

try
{
    /* something */
}
catch( Exception $e )
{
    if ($e instanceof AError OR $e instanceof BError) {
       // It's either an A or B exception.
    } else {
        // Keep throwing it.
        throw $e;
    }
}

但是使用上述答案中描述的多个捕获块可能会更好。

try
{
    /* something */
}
catch( AError $e )
{
   handler1( $e );
}
catch ( BError $b )
{
   handler2( $e );
}

推荐