PHP捕获多个类型的异常.为什么它会这样


PHP catching mulitple type exceptions. Why does it behave this way?

我正在深化PHP异常。此代码在php7 上运行

class MyErrorException extends ErrorException
{ /* stuff here */}
function uncaught_exception_handler($exception)
{ /* stuff here */ }
function uncaught_error_handler()
{ /* throws new MyErrorException */ }
set_exception_handler('uncaught_exception_handler');
set_error_handler('uncaught_error_handler');
$analyze_case = function($e)
{
    switch (get_class($e)){
        case 'Exception':
            echo "I've caught an Exception" . PHP_EOL;
        break;
        case 'Error':
            echo "I've caught an Error" . PHP_EOL;
        break;
        case 'ErrorException':
            echo "I've caught an ErrorException"  . PHP_EOL;
        break;
        case 'MyErrorException':
            echo "I've caught a MyErrorException"  . PHP_EOL;
        break;
        default:
            echo "I've caught something: " . get_class($e) . PHP_EOL;
        break;
    }
};
echo "Case 8" . PHP_EOL;
try {
    throw new MyErrorException();
} catch (Exception $e) {
    echo "I've caught an Exception" . PHP_EOL;
} catch (ErrorException $e) {
    echo "I've caught an ErrorException" . PHP_EOL;
} catch (MyErrorException $e) {
    echo "I've caught a MyErrorException" . PHP_EOL;
} catch (Error $e) {
    echo "I've caught an Error" . PHP_EOL;
}
echo "Case 9" . PHP_EOL;
try {
    throw new MyErrorException();
} catch (Exception $e) {
    $analyze_case($e);
};
echo "Case 10" . PHP_EOL;
try {
    throw new MyErrorException();
} catch (MyErrorException $e) {
    echo "I've caught a MyErrorException" . PHP_EOL;
} catch (Exception $e) {
    echo "I've caught an Exception" . PHP_EOL;
} catch (ErrorException $e) {
    echo "I've caught an ErrorException" . PHP_EOL;
} catch (Error $e) {
    echo "I've caught an Error" . PHP_EOL;
}

以下是结果:

Case 8
I've caught an Exception
Case 9
I've caught a MyErrorException
Case 10
I've caught a MyErrorException

我不明白:

  • 为什么情况8和10不匹配
  • 更具体地说,为什么在情况8)中抛出的异常没有被catch (MyErrorException $e)块捕获

案例8

在情况8中,第一个catch块捕获您的异常,因为您的异常类MyErrorExceptionErrorException扩展而来,而这是从Exception扩展而来的。所以它已经在第一个接球块中被抓住了。

注意:您的异常可能会被MyErrorExceptionErrorExceptionException捕获,因为它是所有这些类的一部分。但Error无法捕捉到。

案例9

同样,在情况9中,它会被捕获,因为它也是一个Exception,但由于您在交换机状态中检查了类,所以您得到了MyErrorException。因为您有一个MyErrorException异常。

案例10

在情况10中,它与8中相同,只是MyErrorException现在首先捕获异常,而不是Exception

如果我没有弄错,在情况8中,您会得到一条I've caught an Exception消息,因为您的MyErrorException(间接)继承自Exception。抛出的对象是Exception的实例,执行第一个catch块。

如果您想为Exception的子类提供特定的catch块,那么应该将它们放在第一位。