要求
我们在网络服务器上运行生产 PHP 代码。在某些情况下,我们希望使用上下文信息来丰富调试输出(例如到 error.log)。上下文可以具有任意字段和结构。
我们的目标是找到一个通用的调试生成函数,它在任何极端情况下都不会产生警告。如果输出只是部分是可以接受的。
TL; 博士
所有三个 PHP 标准函数都会在特定上下文中导致警告:
print_r和var_dump无法处理连接关闭的 mysqli 对象
var_export无法处理递归
题
有没有办法将任意对象的上下文作为人类可读的字符串返回?
测试用例
// Dealing with recursion:
$recObj = new stdClass();
$recObj->recursion = $recObj;
print_r ($recObj); // works
var_export($recObj); // throws: "Warning: var_export does not handle circular references"
var_dump ($recObj); // works
// dealing with mysqli
$mysqli = mysqli_connect('mysql', 'root', 'myPass', 'mysql');
print_r ($mysqli); // works
var_export($mysqli); // works as in "does not throw warnings" but all values are null
var_dump ($mysqli); // works
// Try again with closed connection
mysqli_close($mysqli);
print_r ($mysqli); // throws: "Warning: print_r(): Couldn't fetch mysqli"
var_export($mysqli); // works (again all values are null)
var_dump ($mysqli); // throws: Warning: var_dump(): Couldn't fetch mysqli
根据关闭的 mysqli 连接的相关性:如果您在错误处理程序或注册的关闭函数中进行上下文打印(这是一个很好的位置),一旦您到达该连接,mysqli 对象将已经自动关闭连接处理程序。
如您所见,没有任何内置输出方法能够返回您抛出的任何上下文。
考虑的选项
可以使用@notation 来抑制警告。但是,注册的错误处理程序和关闭函数仍然会被错误调用,并且需要自定义逻辑来忽略该特定错误。这可能会隐藏真正的错误,并且如果处理像 sentry.io 这样的 3rd 方错误跟踪系统也会变得非常烦人
该serialize()
函数在任何情况下都不会产生警告,但缺乏人类可读性。
该json_encode()
函数可以比序列化更具可读性,但它在递归测试用例中不返回任何内容......
不负相思意