📄 正在查看:twcms/kongphp/base/debug.class.php
1<?php
2/**
3 * Copyright (C) 2013-2014 www.kongphp.com All rights reserved.
4 * Licensed http://www.gnu.org/licenses/lgpl.html
5 * Author: wuzhaohuan <kongphp@gmail.com>
6 */
7
8class debug{
9 /**
10 * 初始化 debug 操作
11 */
12 public static function init() {
13 if(DEBUG) {
14 error_reporting(E_ALL | E_STRICT);
15 register_shutdown_function(array('debug', 'shutdown_handler')); // 程序关闭时执行
16 }else{
17 error_reporting(0); // 关闭错误输出
18 }
19 function_exists('ini_set') && ini_set('display_errors', 'On');
20 set_error_handler(array('debug', 'error_handler')); // 设置错误处理方法
21 set_exception_handler(array('debug', 'exception_handler')); // 设置异常处理方法
22 }
23
24 /**
25 * 错误处理
26 * @param string $errno 错误类型
27 * @param string $errstr 错误消息
28 * @param string $errfile 错误文件
29 * @param int $errline 错误行号
30 */
31 public static function error_handler($errno, $errstr, $errfile, $errline) {
32 if(!empty($_ENV['_exception'])) return;
33
34 // 兼容 php 5.3 以下版本
35 defined('E_DEPRECATED') || define('E_DEPRECATED', 8192);
36 defined('E_USER_DEPRECATED') || define('E_USER_DEPRECATED', 16384);
37
38 $error_type = array(
39 E_ERROR => '运行错误',
40 E_WARNING => '运行警告',
41 E_PARSE => '语法错误',
42 E_NOTICE => '运行通知',
43 E_CORE_ERROR => '初始错误',
44 E_CORE_WARNING => '初始警告',
45 E_COMPILE_ERROR => '编译错误',
46 E_COMPILE_WARNING => '编译警告',
47 E_USER_ERROR => '用户定义的错误',
48 E_USER_WARNING => '用户定义的警告',
49 E_USER_NOTICE => '用户定义的通知',
50 E_STRICT => '代码标准建议',
51 E_RECOVERABLE_ERROR => '致命错误',
52 E_DEPRECATED => '代码警告',
53 E_USER_DEPRECATED => '用户定义的代码警告',
54 );
55
56 $errno_str = isset($error_type[$errno]) ? $error_type[$errno] : '未知错误';
57 $s = "[$errno_str] : $errstr";
58 if(DEBUG) {
59 throw new Exception($s);
60 }else{
61 // 线上模式放宽一些,只记录日志,不中断程序执行
62 if(in_array($errno, array(E_NOTICE, E_USER_NOTICE, E_DEPRECATED))) {
63 log::write($s);
64 }else{
65 throw new Exception($s);
66 }
67 }
68 }
69
70 /**
71 * 异常处理
72 * @param int $e 异常对象
73 */
74 public static function exception_handler($e) {
75 DEBUG && $_ENV['_exception'] = 1; // 只输出一次
76
77 // 第1步正确定位
78 $trace = $e->getTrace();
79 if(!empty($trace) && $trace[0]['function'] == 'error_handler' && $trace[0]['class'] == 'debug') {
80 $message = $e->getMessage();
81 $file = $trace[0]['args'][2];
82 $line = $trace[0]['args'][3];
83 }else{
84 $message = '[程序异常] : '.$e->getMessage();
85 $file = $e->getFile();
86 $line = $e->getLine();
87 }
88 $message = self::to_message($message);
89
90 // 第2步写日志 (暂不使用 error_log() )
91 log::write("$message File: $file [$line]");
92
93 // 第3步根据情况输出错误信息
94 try{
95 core::ob_clean();
96 if(R('ajax', 'R')) {
97 if(DEBUG) {
98 $kp_error = "$message File: $file [$line]<br><br>".str_replace("\n", '<br>', $e->getTraceAsString());
99 }else{
100 $len = strlen($_SERVER['DOCUMENT_ROOT']);
101 $file = substr($file, $len);
102 $kp_error = "$message File: $file [$line]";
103 }
104 echo json_encode(array('kp_error' => $kp_error));
105 }else{
106 if(DEBUG) {
107 self::exception($message, $file, $line, $e->getTraceAsString());
108 }else{
109 $len = strlen($_SERVER['DOCUMENT_ROOT']);
110 $file = substr($file, $len);
111 self::sys_error($message, $file, $line);
112 }
113 }
114 }catch(Exception $e) {
115 echo get_class($e)." thrown within the exception handler. Message: ".$e->getMessage()." on line ".$e->getLine();
116 }
117 }
118
119 /**
120 * 输出异常信息
121 * @param string $message 异常消息
122 * @param string $file 异常文件
123 * @param int $line 异常行号
124 * @param string $tracestr 异常追踪信息
125 */
126 public static function exception($message, $file, $line, $tracestr) {
127 include KONG_PATH.'tpl/exception.php';
128 }
129
130 /**
131 * 数组转换成HTML代码 (支持双行变色)
132 * @param array $arr 一维数组
133 * @param int $type 显示类型
134 * @param boot $html 是否转换为 HTML 实体
135 * @return string
136 */
137 public static function arr2str($arr, $type = 2, $html = TRUE) {
138 $s = '';
139 $i = 0;
140 foreach($arr as $k => $v) {
141 switch ($type) {
142 case 0:
143 $k = ''; break;
144 case 1:
145 $k = "#$k "; break;
146 default:
147 $k = "#$k => ";
148 }
149
150 $i++;
151 $c = $i%2 == 0 ? ' class="even"' : '';
152 $html && is_string($v) && $v = htmlspecialchars($v);
153 if(is_array($v) || is_object($v)) {
154 $v = gettype($v);
155 }
156 $s .= "<li$c>$k$v</li>";
157 }
158 return $s;
159 }
160
161 /**
162 * 程序关闭时执行
163 */
164 public static function shutdown_handler() {
165 if(empty($_ENV['_exception'])) {
166 if($e = error_get_last()) {
167 core::ob_clean();
168 $message = $e['message'];
169 $file = $e['file'];
170 $line = $e['line'];
171 if(R('ajax', 'R')) {
172 if(!DEBUG) {
173 $len = strlen($_SERVER['DOCUMENT_ROOT']);
174 $file = substr($file, $len);
175 }
176 $kp_error = "[致命错误] : $message File: $file [$line]";
177 echo json_encode(array('kp_error' => $kp_error));
178 }else{
179 self::sys_error('[致命错误] : '.$message, $file, $line);
180 }
181 }
182 }
183 }
184
185 /**
186 * 输出系统错误
187 * @param string $message 错误消息
188 * @param string $file 错误文件
189 * @param int $line 错误行号
190 */
191 public static function sys_error($message, $file, $line) {
192 include KONG_PATH.'tpl/sys_error.php';
193 }
194
195 /**
196 * 获取错误定位代码
197 * @param string $file 错误文件
198 * @param int $line 错误行号
199 * @return array
200 */
201 public static function get_code($file, $line) {
202 $arr = file($file);
203 $arr2 = array_slice($arr, max(0, $line - 5), 10, true);
204
205 $s = '<table cellspacing="0" width="100%">';
206 foreach ($arr2 as $i => &$v) {
207 $i++;
208 $v = htmlspecialchars($v);
209 $v = str_replace(' ', ' ', $v);
210 $v = str_replace(' ', ' ', $v);
211 $s .= '<tr'.($i == $line ? ' style="background:#faa;"' : '').'><td width="40">#'.$i."</td><td>$v</td>";
212 }
213 $s .= '</table>';
214 return $s;
215 }
216
217 /**
218 * 过滤消息内容
219 * @param string $s 消息内容
220 * @return string
221 */
222 public static function to_message($s) {
223 $s = strip_tags($s);
224 if(strpos($s, 'mysql_connect') !== false) {
225 $s .= ' [连接数据库出错!配置信息见 config.inc.php]';
226 }
227 return $s;
228 }
229
230 /**
231 * 输出追踪信息
232 */
233 public static function sys_trace() {
234 include KONG_PATH.'tpl/sys_trace.php';
235 }
236}
237?>
238