2016-11-01 44 views
1

我製作了自定義錯誤處理程序(請參見下文),它工作得很好。我添加了用於打印和記錄錯誤的方法add()。基本上它處理所有的PHP註冊錯誤。正確的方式跟蹤錯誤行和文件號碼。與使用自定義錯誤處理方法的自定義函數中的debug_backtrace()

我試圖添加add_error()函數以外的類,爲更多的開發人員友好使用添加錯誤。 我遇到的問題是,我想從中得到適當的文件&,但使用debug_backtrace()似乎太複雜了。我的意思是..它的竅門,但它返回其他不必要的東西的數組,我試着過濾數組,返回文件和線錯誤被稱爲,但沒有運氣。

如果我打電話$錯誤 - >添加( '測試', '測試')例如從load.php文件,其中頂部的類文件錯誤handle.php是包括,它返回

C:\WebServer\www\projects\backend-framework\includes\error-handle.php:144: 
array (size=2) 
    0 => 
    array (size=7) 
     'file' => string 'C:\WebServer\www\projects\backend-framework\load.php' (length=52) 
     'line' => int 34 
     'function' => string 'add' (length=3) 
     'class' => string 'ErrorHandle' (length=11) 
     'object' => 
     object(ErrorHandle)[1] 
      public 'count' => int 0 
      public 'last_error' => null 
      public 'errors' => 
      array (size=0) 
       ... 
      public 'debug' => int 1 
      public 'report_errors' => int 1 
      public 'log_errors' => int 1 
     'type' => string '->' (length=2) 
     'args' => 
     array (size=2) 
      0 => string 'test' (length=5) 
      1 => string 'test' (length=5) 
    1 => 
    array (size=4) 
     'file' => string 'C:\WebServer\www\projects\backend-framework\index.php' (length=53) 
     'line' => int 2 
     'args' => 
     array (size=1) 
      0 => string 'C:\WebServer\www\projects\backend-framework\load.php' (length=52) 
     'function' => string 'require_once' (length=12) 

test: test in C:\WebServer\www\projects\backend-framework\index.php on line 2 

正如你可以看到它返回的的index.php代替load.php

Bascially每當我打電話add_error()$錯誤 - >添加()我需要得到正確的文件&行,其中的函數從調用。可能通過使用debug_backtrace()以及一些高級過濾。

我會感謝任何指導或想法如何得到這個結果。 在此先感謝!

自定義錯誤處理程序:

<?php 
/** Custom error handle **/ 
class ErrorHandle { 
    public $count = 0; 
    public $last_error; 
    public $errors = array(); 
    public $debug; 
    public $report_errors; 
    public $log_errors; 

    function __construct($debug = false, $report_errors = false, $log_errors = true){ 
     // Set error report & log args 
     $this->debug = $debug; 
     $this->report_errors = $report_errors; 
     $this->log_errors = $log_errors; 

     // Setup error reporting & logging 
     $this->report_errors($this->report_errors); 
     $this->log_errors($this->log_errors); 


     // Register error handle 
     set_error_handler(array($this, 'error_handler')); 
     // Register fatal error handle 
     register_shutdown_function(array($this, 'fatal_error_handler')); 
    } 

    function error_handler($type, $message, $file, $line){ 
     $html_message = ''; 
     switch ($type) { 
      case E_ERROR: 
       $error_type = 'Runtime Error'; 
       break; 
      case E_WARNING: 
       $error_type = 'Runtime Warning'; 
       break; 
      case E_PARSE: 
       $error_type = 'Runtime Parse'; 
       break; 
      case E_NOTICE: 
       $error_type = 'Runtime Notice'; 
       break; 
      case E_CORE_ERROR: 
       $error_type = 'Core Error'; 
       break; 
      case E_CORE_WARNING: 
       $error_type = 'Core Warning'; 
       break; 
      case E_COMPILE_ERROR: 
       $error_type = 'Compile Error'; 
       break; 
      case E_COMPILE_WARNING: 
       $error_type = 'Compile Warning'; 
       break; 
      case E_USER_ERROR: 
       $error_type = 'User Error'; 
       break; 
      case E_USER_WARNING: 
       $error_type = 'User Warning'; 
       break; 
      case E_USER_NOTICE: 
       $error_type = 'User Notice'; 
       break; 
      case E_STRICT: 
       $error_type = 'PHP Suggestion'; 
       break; 
      case E_RECOVERABLE_ERROR: 
       $error_type = 'PHP Notice'; 
       break; 
      case E_DEPRECATED: 
       $error_type = 'PHP Warning'; 
       break; 
      case E_USER_DEPRECATED: 
       $error_type = 'PHP Deprecation'; 
       break; 
      default: 
       $error_type = 'Unknown'; 
     } 

     $this->add($error_type, $message, $file, $line); 
    } 

    // Fatal error handler 
    function fatal_error_handler() { 
     $last_error = error_get_last(); 

     if(in_array($last_error['type'],array(E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR, E_CORE_WARNING, E_COMPILE_WARNING, E_PARSE))){ 
      $this->error_handler($last_error['type'], $last_error['message'], $last_error['file'], $last_error['line']); 
     } 

     die(); 
    } 

    // Turn ON/OFF display errors 
    function report_errors($bool=false){ 

     ini_set('display_startup_errors', 0); 
     ini_set('docref_root', 0); 
     ini_set('docref_ext', 0); 

     if($bool){ 
      error_reporting(999999999); 
      ini_set('error_reporting', 999999999); 
      ini_set('display_errors', 1); 

      ini_set('report_memleaks', 1); 
      ini_set('track_errors', 1); 
      ini_set('display_startup_errors', 1); 

      return true; 
     }else{ 
      error_reporting(0); 
      ini_set('error_reporting', 0); 
      ini_set('display_errors', 0); 

      return false; 
     } 
    } 

    function log_errors($bool){ 
     if($this->log_errors){ 
      ini_set("log_errors", 1); 
      ini_set("error_log", LOGS_DIR . 'php-error_' . date('d.m.y') . '.txt'); 
      return true; 
     } 
     return false; 
    } 

    function add($type, $message, $file = '', $line = 0){ 

     $html_message = ''; 
     $backtrace = debug_backtrace(); 


     if ($file == '') $file = $backtrace[1]['file']; 
     if ($line == 0) $line = $backtrace[1]['line']; 

     //var_dump($backtrace); 

     $error = array(
      'type'  => $type, 
      'message' => $message, 
      'file'  => $file, 
      'line'  => $line 
     ); 

     if(!in_multi_array($error, $this->errors)){ 
      $this->count++; 
      $this->errors[$this->count] = $error; 
      $this->last_error = $this->errors[$this->count]; 

      if($this->report_errors == true) echo $type . ': <strong>' . $message . '</strong> ' . '<i>in</i> <u>' . $file . '</u> <i>on line</i> <strong>' . $line . '</strong></i></br>'; 

      if($this->log_errors == true) error_log($type . ': ' . $message . ' in ' . $file . ' on line ' . $line); 
      return true; 
     } 
     return false; 
    } 

} 
?> 

回答

0

好吧,我做了一個小小的工作。 這是方法ErrorHandle類:

 /** 
    * Report (print), Log error 
    * Use this function inside functions or methods. If you need 
    * need to add custom error outside - use global add_error() function. 
    * (This is because there is not yet a proper debug_backtrace method to use 
    * to return error FILE name & LINE number) properly!!! 
    */ 
    public function add($type, $message, $file = '', $line = 0){ 

     $html_message = ''; 

     /** 
     * WARNING! This is beta version 
     * If custom error is added, we need to backtrace it & filter the result to 
     * get accurate FILE name & LINE number. 
     */ 
     if($file == '' || $line == 0) : 

      $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); 

      // Filtering - if we find something to exclude, we remove it to get closer to actual file & line nr. 
      foreach ($backtrace as $key => $value) { 
       // The filter 
       if((isset($value) && strpos($value['file'], 'error-handle.php')) || (isset($value['class']) && $value['class'] == 'ErrorHandle' && $value['function'] == 'add')){ 
        array_splice($backtrace, $key, 1); 
       } 
      } 

      if ($file == '') $file = $backtrace[0]['file']; 
      if ($line == 0) $line = $backtrace[0]['line']; 

     endif; 


     $error = array(
      'type'  => $type, 
      'message' => $message, 
      'file'  => $file, 
      'line'  => $line 
     ); 

     // Let's check if we haven't stored the same error previously, so there's no dublication 
     if(!in_multi_array($error, $this->errors)){ 
      $this->count++; 
      $this->errors[$this->count] = $error; 
      $this->last_error = $this->errors[$this->count]; 

      // Report Error Message 
      if($this->report_errors) echo $type . ': <strong>' . $message . '</strong> ' . '<i>in</i> <u>' . $file . '</u> <i>on line</i> <strong>' . $line . '</strong></i></br>'; 
      // Log Error Message 
      if($this->log_errors) error_log($type . ': ' . $message . ' in ' . $file . ' on line ' . $line); 

      return true; 
     } 
     return false; 
    } 

和類之外我還創建了這個功能:

/** 
* Add error 
* Don't use this function inside functions or methods!!! 
* If you need to add error inside function or method - use $error->add() function. 
* (This is because there is not yet a proper debug_backtrace method to use 
* to return error FILE name & LINE number) properly!!! 
*/ 
function add_error($type, $message, $file = '', $line = 0){ 
    global $error; 
    return $error->add($type, $message, $file, $line); 
} 

一切似乎很好地工作。嘗試在不同的深度&水平。 但..唯一的問題,我不能找到一種方法來解決 - $錯誤 - >添加()必須函數內一直使用&方法,而add_error()函數外(不能在功能&方法中使用)。不知道爲什麼,但這是以開始:)

1

正如你可以看到它返回的的index.php代替load.php

它實際上兩者都返回,它只是你如果您確實想要$backtrace[0]['file'],請訪問$backtrace[1]['file']

我認爲debug_backtrace在考慮深度時必須考慮更多的意義。使用下面的示例作爲起點:

function debug($depth) { 
    $trace = debug_backtrace()[$depth]; 
    if (isset($trace['file'], $trace['line'])) { 
     return [$trace['file'], $trace['line']]; 
    } 
    return false; 
} 

// check depth 0 
if (list($file, $line) = debug(0)) { 
    // ... 
} 

有了這個,你可以嘗試,看看有什麼深入的你實際上是尋找。當然,這一切都取決於你的應用程序是如何組織的,因此某些文件可能有不同的深度。

+0

謝謝。我會盡力尋找。 與此同時,我已經討論了這種方法,這似乎是在頂層函數上工作。 '$ dbt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS,2); $ caller = isset($ dbt [1] ['function'])? $ dbt [1] ['function']:null;' 淺談深度 - 這就是爲什麼我想過爲** debug_backtrace()**過濾的主要原因 –