有人可以告诉我在 PHP 中看到此错误的最常见原因:
无法在...中破坏活动的 lambda 函数
我猜想某处有代码试图破坏一个包含对自身的引用的闭包,编译器对此感到恼火。
我们比我想要的更频繁地得到这些,我想知道我们使用的是什么模式,这可能是导致它的罪魁祸首。
我会附上一个代码片段,但错误通常指向一个文件,而不是文件中可能提供提示的行。
这样的致命错误将导致如下代码:
set_exception_handler(function ($e) {
echo "My exception handler";
restore_exception_handler();
throw new Exception("Throw this instead.");
});
throw new Exception("An exception");
或者像这样:
function destroy_handler() {
restore_exception_handler();
}
function update_handler() {
destroy_handler();
}
set_exception_handler(function ($e) {
echo "My exception handler";
update_handler();
throw new Exception("Throw this instead.");
});
throw new Exception("An exception");
当抛出异常时,将set_exception_handler()
执行给定的回调,并且一旦restore_exception_handler()
调用,就会发生致命错误,因为对该闭包的相同引用正在其自己的范围内被销毁(或重新分配)(在 in 的示例中也是如此hanskrentel at yahoo dot de
)发布的链接Sameer K
)。
您可以从第二个示例中看到,即使使用嵌套范围,也会发生同样的情况。这是因为restore_exception_handler
将破坏最后设置的异常处理程序,而不是它的副本(这就像在您仍在评估将为变量赋予初始值的表达式时重新分配变量或取消设置它)。
如果您说代码中的错误指向另一个文件,我建议您检查 lambda 中的所有调用,这些调用在其他文件中的函数和/或方法中执行“跳转”,并检查您是否正在重新分配或销毁对lambda 本身。
将set_exception_handler
返回之前的异常处理程序:
返回先前定义的异常处理程序的名称,或错误时返回 NULL。如果没有定义先前的处理程序,也返回 NULL。 php.net:set_exception_handler
<?php
class MyException extends Exception {}
set_exception_handler(function(Exception $e){
echo "Old handler:".$e->getMessage();
});
$lastHandler = set_exception_handler(function(Exception $e) use (&$lastHandler) {
if ($e instanceof MyException) {
echo "New handler:".$e->getMessage();
return;
}
if (is_callable($lastHandler)) {
return call_user_func_array($lastHandler, [$e]);
}
throw $e;
});
触发异常处理程序:
throw new MyException("Exception one", 1);
输出:New handler:Exception one
throw new Exception("Exception two", 1);
输出:Old handler:Exception two