将异常抛出到下一个Catch Block

时间:2014-12-07 21:48:43

标签: php exception exception-handling

我想捕获一个自定义异常,对它执行一些逻辑,如果失败,则将其抛给更通用的catch块。像这样:

class My_Exception extends Exception {
    protected $_nonFatal = false;

    public function __construct($value, $nonFatal = false) {
        $this->_nonFatal = (bool)$nonFatal;

        return parent::__construct($value);
    }

    public function isNonFatal() {
        return (bool)$this->_nonFatal;
    }
}

try {

} catch (My_Exception $e) {
    if ($e->isNonFatal) {
        // #1
        // Err gently
    }

    // #2
    // The error was fatal, so keep throwing it
    throw new Exception($e->getMessage());

} catch (Exception $e) {
    // #3
    echo 'An exception was caught with the message '.$e->getMessage();
}

所以我抓住My_Exception,检查它是否是非致命错误。如果是这样,请轻轻地(第1节)。如果不是(第2节),我希望触发第二个捕获,(第3节。)相反,第2节中的throw new Exceptiontry/catch/catch全部放在一起。

我可以在$e的类上使用switch语句,但我觉得这很麻烦。有没有一种标准的方法可以解决这个问题?

2 个答案:

答案 0 :(得分:2)

  

如果不是(第2节),我希望触发第二次捕获

尝试/捕获块不会像那样工作 - 一个catch块总是会突破try / catch块;它没有"经过"比如switch语句可以。

您需要使用另一个try / catch块包装代码。

try {
    try {
        // ...
    } catch (My_Exception $e) {
        if ($e->isNonFatal) {
            // #1
            // Err gently
        }

        // #2
        // The error was fatal, so keep throwing it
        throw new Exception($e->getMessage());
    }
} catch (Exception $e) {
    // #3
    echo 'An exception was caught with the message '.$e->getMessage();
}

  

有没有一种标准的方法可以解决这个问题?

没有真正的"标准"这样做的方式;通常你不会在另一个例外中概括一个例外,但如果申请是正确的,那么这就是你想要这样做的。

管理异常链的更好方法是在构造函数中pass your custom exception a the previous exception。这样,无论选择异常,都可以使用Exception.getPrevious(),并在更通用的情况下显示您的例外情况。

答案 1 :(得分:1)

不幸的是,catch块无法处理在同级catch块之前抛出的任何异常,即使它是从另一个函数调用中抛出的。 换句话说,从块#{<1}}内部抛出的任何未处理的异常将不会从块#2 内部看到(但将由调用堆栈中的偶数上部catch块处理)

#1

那么,坦率地说,立即嵌套的try / catch块看起来很难看 如果您的应用程序逻辑不是太复杂,您可以使用instanceof运算符保持代码整洁。

try {
    error_prone_code();
} catch (My_Exception $e) { // #1
    throw new \Exception($e->getMessage());
} catch (Exception $e) { // #2
    echo "Something bad happend: {$e->getMessage()}";
}