如何最好地处理在catch块中引发的异常?

时间:2019-07-31 10:24:28

标签: php

假设我有一个try / catch块,如果发生不好的情况,我需要在catch块中进行一些清理。 然后,我想抛出原始异常,让应用程序代码处理它。

例如,可以回滚这样的数据库事务:

try {
  startTransaction();
  doSomethingThatThrowsAnException();
} catch (Exception $e) {
  rollbackTransaction();
  throw $e;
}

很好,但是回滚可能会失败并且也会引发异常。然后,我的应用程序将仅看到回滚异常,而不是原始异常。然后,我将错过最有用的信息,这是不好的。

所以我可以将代码更改为此:

try {
  startTransaction();
  doSomethingThatThrowsAnException();
} catch (Exception $e) {
  try {
    rollbackTransaction();
  } catch (Exception $ex) {
    // Do nothing
  }
  throw $e;
}

那更好,但是现在我不知道清理/回滚也失败了。回滚功能中可能存在一个我永远不会发现的错误。 我想获得有关这两种例外情况的完整信息。

到目前为止,我能想到的最好的办法是创建一个新异常,保留有关回滚异常的消息,并像以前一样发送原始异常:

try {
  startTransaction();
  doSomethingThatThrowsAnException();
} catch (Exception $e) {
  try {
    rollbackTransaction();
  } catch (Exception $ex) {
    throw new Exception($ex->getMessage(), $ex->getCode(), $e);
  }
  throw $e;
}

但这并不完美,我仍然会丢失一些有关回滚异常的信息,例如其堆栈跟踪。

我还尝试创建另一个包含这两个异常的Exception-class:

try {
  startTransaction();
  doSomethingThatThrowsAnException();
} catch (Exception $e) {
  try {
    rollbackTransaction();
  } catch (Exception $ex) {
    throw new MultiException($e, $ex);
  }
  throw $e;
}

class MultiException extends Exception
{
    private $exceptions = [];

    public function __construct(...$exceptions)
    {
        $this->exceptions = $exceptions;
    }

    public function __toString()
    {
        return implode("\n", $this->exceptions);
    }
}

但是我不确定这在各种日志记录框架中如何发挥作用。例如,只能覆盖__toString()方法,而不能覆盖getTrace()。

是否有更好的方法或最佳实践来处理此类案件?

0 个答案:

没有答案