考虑下面的示例代码片段:
/**
* @throws \DomainException
*/
public function doFoo()
{
try {
// Do a unit of work with in a transaction.
// This code could throw a SomeOtherException.
// In this case the transaction should be rolled back
// and a \DomainException should be thrown.
} catch (SomeOtherException $e1) {
try {
$this->pdo->rollback();
throw new \DomainException("Failed", 0, $e1);
} catch (\PDOException $e2) {
// $e2 is lost!
throw new \DomainException("Failed even more", 0, $e1);
}
}
}不可变的约定只允许抛出DomainException。我对第二个catch块(内部catch (PDOException $e2))感兴趣。我可以使用$e1或$e2作为前一个异常,但不能同时使用两者。
我不喜欢一个异常被吞噬(在本例中是$e2)。那么,我如何抛出完整的错误信息,即包含$e1和$e2的\DomainException?我正在考虑将$e1添加到$e2的根目录中,并像以前一样使用$e2,但是PHP的Exception是不可变的。
编辑: PDO只是一个典型的用例。我也可以是对这两个异常的堆栈跟踪感兴趣的任何其他API。
Edit2:将其视为一个不能更改的接口的实现。
Edit3: Java的Throwable.addSupressed()非常适合这里。这可能有助于理解用例。
发布于 2015-07-29 03:48:46
您可能会这样做:
catch (\PDOException $e2) {
// Probably you do even need to pass more parameters
// to PDOException() to make it an exact "clone|brother".
// However, should get the concept out of it.
$e = new \PDOException($e2->getMessage(), 0, $e1);
throw $e;
}不幸的是,在这种情况下,您将丢失$e2 ( PDOException)的堆栈跟踪。要解决此问题,您可以创建具有两个附加属性(如$domainException和$rollbackException )的自定义异常。您可以简单地覆盖该类中的getMessage(),并组合嵌套异常的消息,以在日志文件中获得一致的错误消息。
顺便说一句,这是个好问题。我很好奇别人会怎么说。
发布于 2015-08-01 17:04:18
我发现finally确实是自动完成所有事情的:
try {
throw new Exception("A");
} finally {
throw new Exception("B");
}这将打印以下内容:
Test.php致命错误:未捕获异常' exception‘,消息'A’位于/
/malkusch/tmp/test.php:4堆栈跟踪:
#0 {main}
/home/malkusch>/tmp/test.php:7堆栈跟踪中包含消息'B‘的下一个异常' exception’:
#0 {main}
我没有想到这是因为两个异常之间没有因果关系,但这是可以接受的,因为Exception::getPrevious()没有进一步的语义指定。
不幸的是,这是未记录的行为,不能被认为是稳定的。Bug #68270表明,目前还没有人知道预期的行为应该是什么。所以依赖它是不安全的。让我们看看discussion in internals会带来什么。
https://stackoverflow.com/questions/31685584
复制相似问题