Java的一个PHP挂件Throwable.addSuppressed()

时间:2015-07-28 19:37:57

标签: php

考虑这个示例性代码片段:

/**
 * @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()完全适合这里。这可能有助于理解用例。

2 个答案:

答案 0 :(得分:0)

您可能会这样做:

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()并组合嵌套异常的消息,以在日志文件中获取一致的错误消息。

不,这是一个很好的问题。我很好奇其他人会说些什么。

答案 1 :(得分:0)

我发现确实finally会自动完成所有操作:

try {
    throw new Exception("A");

} finally {
    throw new Exception("B");
}

这将打印:

  

PHP致命错误:未捕获的异常'异常'消息' A'在/home/malkusch/tmp/test.php:4   堆栈跟踪:

     

#0 {main}

     

下一个例外'异常'留言' B'在/home/malkusch> /tmp/test.php:7   堆栈跟踪:

     

#0 {main}

我没有想到,因为两个例外之间没有因果关系,但是Exception::getPrevious()可接受的没有指定进一步的语义。

不幸的是,这是无证件行为,不能被视为稳定。 Bug #68270表明目前没有人知道预期的行为应该是什么。所以依靠它是不安全的。让我们看看discussion in internals会带来什么。