我正在编写PHP方法来使用params来打印callstack。 原因是它将用作公共API的输出(在调试模式下),因此它不能显示所有内容,只显示保存信息。
我希望看到类似的内容:
- config.php中的Config-> saveToFile(resource:file):: 456
- config.php :: 123
中的Config-> backup('config.bak') 醇>
但是,当我致电debug_backtrace()
并解析args
值时,我无法使用方法gettype()
,is_resource()
和get_resource_type()
因为总是说变量属于未知类型:
- 配置> saveToFile(未知类型:资源ID#99)在config.php :: 456
中- config.php :: 123
中的Config-> backup('config.bak') 醇>
用于解析args的代码是:
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中都没有找到任何相关内容。
系统:
答案 0 :(得分:1)
所以问题是资源只有在打开时才能被识别为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);
}