Eri*_*zen 5 php destructor exception php-internals
我如何查看当前是否存在异常,即堆栈正在展开?
在下面的示例中,您将如何实施isExceptionInFlight()?
<?php
class Destroyer
{
function __destruct() {
if (isExceptionInFlight()) {
echo 'failure';
} else {
echo 'success';
}
}
}
function isExceptionInFlight() {
// ?????
}
function createAndThrow()
{
$var = new Destroyer;
throw new \Exception;
}
createAndThrow();
Run Code Online (Sandbox Code Playgroud)
这样做的目的是实现 D 的scope语句,该语句可作为多种其他语言的库使用。这使您可以摆脱嵌套的 try-catch 块,从而更轻松地正确执行回滚事务。
我环顾过 Zend PHP 引擎,executor_globals.exception似乎就是我正在寻找的东西(https://github.com/php/php-src/blob/master/Zend/zend_globals.h)。然而,nullptr当我在 __destruct() 期间检查它时,该值始终是。知道我接下来应该看哪里吗?
检查executor_globals.opline_before_exception取得了一些进展。但是,它不会重置为nullptr捕获异常时的值。
我找到了以下代码(第135行)
/* Make sure that destructors are protected from previously thrown exceptions.
* For example, if an exception was thrown in a function and when the function's
* local variable destruction results in a destructor being called.
*/
old_exception = NULL;
if (EG(exception)) {
if (EG(exception) == object) {
zend_error_noreturn(E_CORE_ERROR, "Attempt to destruct pending exception");
} else {
old_exception = EG(exception);
EG(exception) = NULL;
}
}
zend_call_method_with_0_params(&obj, object->ce, &destructor, ZEND_DESTRUCTOR_FUNC_NAME, NULL);
if (old_exception) {
if (EG(exception)) {
zend_exception_set_previous(EG(exception), old_exception);
} else {
EG(exception) = old_exception;
}
}
Run Code Online (Sandbox Code Playgroud)
这似乎积极阻止我做我想做的事,并解释了为什么executor_globals.exception总是如此nullptr。
虽然我不推荐,但我过去已经实现过。我的方法(简单地说)是这样的:
实现自定义异常类
class MyException extends Exception {
public static $exceptionThrown = false;
public function __construct($your parameters) {
self::$exceptionThrown = true;
}
}
Run Code Online (Sandbox Code Playgroud)
现在,每个异常都应该是您自己的异常实现,而不是默认的异常。
class Destroyer {
public function __destruct() {
if(MyException::exceptionThrown() {
Database::rollback();
} else {
Database::commit();
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
367 次 |
| 最近记录: |