2016-08-02 80 views
0

我正在編寫PHP方法以使用params很好地打印調用堆棧。 原因是它將用作公共API的輸出(在調試模式下),因此它不能顯示所有內容並只顯示保存信息。無法從回溯中識別PHP資源(調用堆棧)

我希望看到這樣的事情:

  1. Config->的SaveToFile(資源:文件)在config.php :: 456
  2. Config->備份('config.bak可以「)在config.php :: 123

但是,當我打電話debug_backtrace()並解析args價值,我無法使用方法gettype()is_resource()get_resource_type(),因爲它總是說變量是未知類型的:

  1. Config->的SaveToFile(未知類型:資源ID#99)在config.php :: 456
  2. Config->備份( 'config.bak可以')在config.php :: 123

代碼用來解析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文檔,利用gettype()和檢查resource上市diz at ysagoon dot com使用代碼,在我的情況下,它會返回Config->saveToFile(Unknown)

當我在創建資源的代碼中使用方法時,它正確地返回它的類型。

有沒有限制或理由爲什麼資源沒有從回溯識別?我應該在PHP配置中啓用的東西?我在PHP文檔和Google上都沒有發現任何關於此的信息。


系統:

  • XAMPP 3.2.2
  • 的Apache/2.4.17(Win32的)
  • PHP/5.6.15
  • 的Windows 10專業版64週年紀念版1607(10.0 .14393)

回答

1

所以問題是resour ces只能在打開時被識別爲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; 
} 

所以,現在我可以存儲資源創建時:

protected function saveToFile($file) { 
     $debug->traceResourceParams() 

     //... work with file 

     fclose($file); 
} 

$f = fopen('tmp', 'w'); 
$debug->traceNamedResource($f, 'tmp'); 
fclose($f); 

或當它作爲參數傳遞