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

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

有什么办法可以做到吗?还是我得分别抓他们?

AError和Berror有一个共享的基类,但它们还与我希望落入handler2的其他类型共享这个基类,因此不能只捕获基类。


当前回答

嗯,有很多解决方案是为低于7.1的php版本编写的。

下面是另一个简单的方法,适用于那些不想catch all异常且不能创建公共接口的人:

<?php
$ex = NULL
try {
    /* ... */
} catch (FirstException $ex) {
    // just do nothing here
} catch (SecondException $ex) {
    // just do nothing here
}
if ($ex !== NULL) {
    // handle those exceptions here!
}
?>

其他回答

PHP 7.1提供了捕获多种类型的能力。

所以:

<?php
try {
    /* ... */
} catch (FirstException $ex) {
    $this->manageException($ex);
} catch (SecondException $ex) {
    $this->manageException($ex);
}
?>

and

<?php
try {

} catch (FirstException | SecondException $ex) {
    $this->manageException($ex);
}
?>

在功能上是等同的。

除了穿越,也可以使用goto跨过去。 如果你想看世界燃烧,这很有用。

<?php

class A_Error extends Exception {}
class B_Error extends Exception {}
class C_Error extends Exception {}

try {
    throw new A_Error();
} 
catch (A_Error $e) { goto abc; }
catch (B_Error $e) { goto abc; }
catch (C_Error $e) {
abc:
    var_dump(get_class($e));
    echo "Gotta Catch 'Em All\n";
}

3 v4l.org

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


如果可以修改异常,请使用此答案。

如果不能,可以尝试用Exception捕获所有异常,然后用instanceof检查抛出了哪个异常。

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 );
}

嗯,有很多解决方案是为低于7.1的php版本编写的。

下面是另一个简单的方法,适用于那些不想catch all异常且不能创建公共接口的人:

<?php
$ex = NULL
try {
    /* ... */
} catch (FirstException $ex) {
    // just do nothing here
} catch (SecondException $ex) {
    // just do nothing here
}
if ($ex !== NULL) {
    // handle those exceptions here!
}
?>

从PHP 8.0开始,当您不需要输出错误内容(从变量$e)时,您可以使用更清晰的方式来捕获异常。但是你必须用Throwable替换默认的Exception。

try {
    /* something */
} catch (AError | BError) {
    handler1()
} catch (Throwable) {
    handler2()
}