我的代码中有一个自定义的异常处理程序(曾经正常工作),直到我昨天突然看到这个错误:
PHP Fatal error: Uncaught exception 'Exception' with message 'Serialization of 'Closure' is not allowed' in /raid0/nginx/www/voiceportal/lib/logutils.php:34 Stack trace:
#0 /raid0/nginx/www/voiceportal/lib/logutils.php(34): serialize(Array)
#1 [internal function]: custom_exception_handler(Object(AMQPConnectionException))
#2 {main}
我读到如果尝试序列化匿名函数可能会导致这种情况,但这就是我犯错的原因:
//logutils.php
function custom_exception_handler($exception) {
$trace_id = uniqid();
$trace = serialize(array('trace_id' => $trace_id, 'trace' => $exception->getTrace()));
...
}
不确定它是否是由于尝试序列化getTrace()引起的,但如果我没记错的话,它过去就会工作。
最初的例外是(如跟踪中所示)AMQPConnectionException
。
我想了解导致'Serialization of Closure not allowed'
例外的原因。
谢谢!
答案 0 :(得分:2)
PHP's backtrace structure包括对在堆栈的每个级别调用其方法的对象的引用。当它尝试序列化跟踪时,任何引用闭包的对象(或引用闭包等的引用对象)都将阻止序列化。
在您的情况下,您可以将跟踪重新转换为稍微不那么描述性的形式,或者查找哪些对象包含闭包,并将闭包重新打包为__invoke
个实例,或者在通过实现Serializable
进行序列化时跳过它们,as described here。您在此处的选择取决于您在跟踪中所做的工作。如果仅仅是为了对出现问题的人类可读描述,请考虑使用getTraceAsString()
方法而不是getTrace()
。
答案 1 :(得分:1)
我编写了一个允许任何Exception
序列化的函数。这是通过展平回溯中的复杂值来完成的。
https://gist.github.com/Thinkscape/805ba8b91cdce6bcaf7c
//logutils.php
function custom_exception_handler($exception) {
flattenExceptionBacktrace($exception); // <---- ADD THIS
$trace_id = uniqid();
$trace = serialize(array('trace_id' => $trace_id, 'trace' => $exception->getTrace()));
...
}
答案 2 :(得分:0)
我知道这是一个老话题,但我想推荐自己的library to serializing stack traces。 Object $ stackTrace可以包含值,可以序列化。未序列化的对象将仅包含自定义的变量转储(@see interface)。