我正在编写PHP方法来漂亮地打印带有params的调用堆栈原因是它将被用作公共API的输出(在调试模式下),因此它不能显示所有内容,只能显示保存信息
我想看看这样的东西:
- Config.php中的Config->saveToFile(resource:file):456
- Config.php中的Config->backup('Config.bak'):123
但是,当我调用debug_backtrace()
并解析args
值时,我不能使用方法gettype()
、is_resource()
和get_resource_type()
,因为它总是说变量是未知类型:
- Config.php中的Config->saveToFile(未知类型:Resource id#99):456
- Config.php中的Config->backup('Config.bak'):123
用于解析参数的代码为:
public static function getTrace() {
$trace = debug_backtrace();
$output = [];
foreach ($trace as $call) {
$name = $call['class'] . $call['type'] . $call['function']
//actual code checks for various situations
$args = [];
foreach ($call['args'] as $arg) {
$args[] = self::toString($arg);
}
$name .= '(' . join(', ', $args) . ')';
$output[] = $name . ' in ' . basename($call['file']) . '::' . $call['line'];
}
return $output;
}
protected static function toString($mixed) {
//process known types - arrays, objects, strings, etc.
//...
if (is_resource($mixed)) {
return 'resource: ' . get_resource_type($mixed);
}
return gettype($mixed) . ': ' . $mixed;
}
即使我使用debug_backtrace文档中列出的diz at ysagoon dot com
的代码,该文档使用gettype()
并检查resource
,在我的情况下,它也会返回Config->saveToFile(Unknown)
。
当我在创建资源的代码中使用方法时,它会正确地返回其类型。
没有从回溯中识别资源是否有限制或原因?我应该在PHP配置中启用什么?我在PHP文档和Google中都没有找到任何关于这方面的内容。
系统:
- 示例3.2.2
- Apache/2.4.17(Win32)
- PHP/5.6.15
- Windows 10 Pro x64周年纪念版1607(10.0.14393)
所以问题是资源只能在打开时被标识为resource
。关闭资源后,方法gettype()
、is_resource()
和get_resource_type()
不再将其标识为resource
,而是更改为unknown type
。
$f = fopen('tmp', 'w');
echo gettype($f); //= 'resource'
fclose($f);
echo gettype($f); //= 'Unknown type'
为了在回溯中打印关闭的资源,我创建了两种方法来在资源仍然打开时记住它们:
protected $resources = [];
public function traceResourceParams() {
$trace = debug_backtrace();
$args = [];
foreach ($trace as $call) {
foreach ($call['args'] as $arg) {
if (is_resource($arg) && !array_key_exists(intval($arg), $this->resources)) {
$this->resources[intval($arg)] = self::toString($arg);
}
}
}
}
public function traceNamedResource($resource, $name) {
if (is_resource($resource)) {
$this->resources[intval($resource)] = '{' . get_resource_type($resource) . ': ' . $name . '}';
}
}
并更新了我的toString
方法来检查存储的资源:
protected static function toString($mixed) {
//process known types - arrays, objects, strings, etc.
//...
if (is_resource($mixed)) {
return 'resource: ' . get_resource_type($mixed);
}
//closed resources does not evaluate as resource
//but still convert to resource id using intval()
//so we can match them to previously evaluated resources
$val = intval($mixed);
if ($val && array_key_exists($val, self::getInstance()->resources)) {
return self::getInstance()->resources[$val];
}
return gettype($mixed) . ': ' . $mixed;
}
所以现在我可以在创建资源时存储它:
$f = fopen('tmp', 'w');
$debug->traceNamedResource($f, 'tmp');
fclose($f);
或者当它作为参数传递时:
protected function saveToFile($file) {
$debug->traceResourceParams()
//... work with file
fclose($file);
}