xdebug 的報錯功能非常好用,但由於沒有 nts 的版本,一直以來是我心中的缺憾。
這兩天花了一點時間研究,寫出一個替代用的報錯物件,除了時間和記憶用量無法顯示外,其他都可以做到接近 xdebug 的報錯功能。
我還加上顯示出現錯誤的源碼片段、傳入參數的功能,這個物件還可以繼續改加以完善。

用法:
Zyme_Error::除錯(true);
Zyme_Error::錯誤處理(true);

原始碼在下面:
<?php
final class Zyme_Error {
    static private $除錯 = false;
    static private $詳細 = false;
    static private $間距 = 2;
   
    static function 除錯($除錯 = null){
        $_除錯 = self::$除錯;
        if (false == is_null($除錯)) {
            self::$除錯 = (bool)$除錯;
        }
        return $_除錯;
    }
   
    static function 錯誤處理($設定 = true, $詳細 = false, $間距 = 2){
        static $處理 = false;
        if ($設定) {
            if (false == $處理) {
                set_error_handler(array(__CLASS__, '報錯'));
                $處理 = true;
            }
        } else {
            restore_error_handler();
            $處理 = false;
        }
        self::$詳細 = (bool)$詳細;
        $_間距 = (int)$間距;
        self::$間距 = (0 > $_間距) ? 0 : $_間距;
    }

    static function 報錯($代碼, $訊息, $檔案 = '', $行號 = '', $內容 = array()){
        static $預設 = array('function' => '', 'line' => '', 'file' => '', 'class' => '', 'object' => '', 'type' => '', 'args' => array());
        if (false == self::$除錯 || false == (error_reporting() & $代碼)) {
            return true;
        }
        $除錯 = array_reverse(debug_backtrace());
        array_pop($除錯);

        $輸出 = array();
        $輸出[] = '<table bgcolor="#eeeeec" border="1px" cellspacing="0px" cellpadding="0px">';
        $輸出[] = '<tr><th colspan="3" style="background:#f57900; text-align:left; padding:1ex">' . self::錯誤代碼($代碼) . ' : ' . $訊息 . '</th></tr>';
        $輸出[] = '<tr><td colspan="3" style="padding:1ex">' . $檔案 . '<strong> : </strong>' . $行號 . self::源碼($檔案, $行號) . '</td></tr>';
        $輸出[] = (empty($除錯)) ? '' : '<tr style="background:#e9b96e"><th>#</th><th>Function</th><th>Location</th></tr>';
        foreach ($除錯 as $_索引 => $_內容){
            $輸出[] = self::項目繪製($_索引, $_內容);
        }
        $輸出[] = '</table>';
        echo implode("\n", $輸出), '<br />';
        return true;
    }

    static private function 引用($內容) {
        $_內容 = trim($內容);
        return (empty($_內容)) ? '&nbsp;' : htmlspecialchars($內容, ENT_COMPAT, 'utf-8');
    }

    static private function 參數($參數) {
        return (empty($參數) || false == self::$詳細) ? '' : '<pre style="background:#ffffff; margin:0px; padding:1ex; overflow:auto">' . self::引用(print_r($參數, true)) . '</pre>';
    }

    static private function 源碼($檔案, $行號) {
        static $斷行 = "<br />";
        if (false == is_readable($檔案) || false == self::$詳細) {
            return '';
        }
        $源碼 = explode($斷行, substr(highlight_file($檔案, true), strlen('<code>'), -1 * strlen('</code>')));
        $行數 = count($源碼);
        $_行號 = $行號 - 1;
        $開始 = ($_行號 - self::$間距);
        $結束 = ($_行號 + self::$間距);
        $_開始 = (0 > $開始) ? 0 : $開始;
        $_結束 = ($行數 < $結束) ? $行數 : $結束;
        $格式 = '<div style="color:#000000; display:inline">%0' . ceil(log10($行數)) . 'd<strong> : </strong></div>%s';
        $輸出 = array();
        for ($索引 = $_開始; $索引 <= $_結束; $索引++){
            $_格式 = ($_行號 == $索引) ? '<div style="background:#00ff00; display:inline">' . $格式 . '</div>' : $格式;
            $輸出[] = sprintf($_格式, $索引 + 1, $源碼[$索引]);
        }
        return '<div style="background:#ffffff; padding:1ex; overflow:auto">' . implode($斷行, $輸出) . '</div>';
    }

    static private function 項目繪製($索引, $項目){
        static $預設 = array('function' => '', 'line' => '', 'file' => '', 'class' => '', 'object' => '', 'type' => '', 'args' => array());
        $輸出 = array();
        $_項目 = $項目 + $預設;
        if (empty($_項目['file'])) {
            return '';
        }
        $調用 = (empty($_項目['type'])) ? $_項目['function'] : $_項目['class'] . $_項目['type'] . $_項目['function'];
        $位置 = (empty($_項目['file'])) ? '' : self::引用($_項目['file']) . '<strong> : </strong>' . self::引用($_項目['line']);
       
        $輸出[] = '<tr>';
        $輸出[] = '<td style="padding:1ex; vertical-align:top; text-align:center">' . $索引 . '</td>';
        $輸出[] = '<td style="padding:1ex; vertical-align:top">' . $調用 . self::參數($_項目['args']) . '</td>';
        $輸出[] = '<td style="padding:1ex; vertical-align:top">' . $位置 . self::源碼($_項目['file'], $_項目['line']) . '</td>';
        $輸出[] = '</tr>';
       
        return implode("\n", $輸出);
    }
       
    static private function 錯誤代碼($代碼){
        static $錯誤 = array(
            E_ERROR                            =>    'Error',
            E_WARNING                        =>    'Warning',
            E_PARSE                            =>    'Parse',
            E_NOTICE                        =>    'Notice',
            E_CORE_ERROR                =>    'Core Error',
            E_CORE_WARNING            =>    'Core Warning',
            E_COMPILE_ERROR            =>    'Compile Error',
            E_COMPILE_WARNING        =>    'Compile Warning',
            E_USER_ERROR                =>    'User Error',
            E_USER_WARNING            =>    'User Warning',
            E_USER_NOTICE                =>    'User Notice',
            E_STRICT                        =>    'Strict',
            E_RECOVERABLE_ERROR    =>    'Recoverable Error',
        );
        $輸出 = &$錯誤[$代碼];
        return (isset($輸出)) ? $輸出 : 'Unknown Error';
    }   

}
?>
arrow
arrow
    全站熱搜

    HACGIS 發表在 痞客邦 留言(0) 人氣()