一、效果图:
二、实现代码
代码如下:
// 自定义异常函数 set_exception_handler('handle_exception');
// 自定义错误函数 set_error_handler('handle_error');
/** * 异常处理 * * @param mixed $exception 异常对象 * @author blog.snsgou.com */ function handle_exception($exception) { Error::exceptionError($exception); }
/** * 错误处理 * * @param string $errNo 错误代码 * @param string $errStr 错误信息 * @param string $errFile 出错文件 * @param string $errLine 出错行 * @author blog.snsgou.com */ function handle_error($errNo,$errStr,$errFile,$errLine) { if ($errNo) { Error::systemError($errStr,false,true,false); } }
/** * 系统错误处理 * * @author blog.snsgou.com */ class Error {
public static function systemError($message,$show = true,$save = true,$halt = true) {
list($showTrace,$logTrace) = self::debugBacktrace();
if ($save) { $messageSave = '' . $message . ' PHP:' . $logTrace; self::writeErrorLog($messageSave); }
if ($show) { self::showError('system'," $message",$showTrace,0); }
if ($halt) { exit(); } else { return $message; } }
/** * 代码执行过程回溯信息 * * @static * @access public */ public static function debugBacktrace() { $skipFunc[] = 'Error->debugBacktrace';
$show = $log = ''; $debugBacktrace = debug_backtrace(); ksort($debugBacktrace); foreach ($debugBacktrace as $k => $error) { if (!isset($error['file'])) { // 利用反射API来获取方法/函数所在的文件和行数 try { if (isset($error['class'])) { $reflection = new ReflectionMethod($error['class'],$error['function']); } else { $reflection = new ReflectionFunction($error['function']); } $error['file'] = $reflection->getFileName(); $error['line'] = $reflection->getStartLine(); } catch (Exception $e) { continue; } }
$file = str_replace(SITE_PATH,'',$error['file']); $func = isset($error['class']) ? $error['class'] : ''; $func .= isset($error['type']) ? $error['type'] : ''; $func .= isset($error['function']) ? $error['function'] : ''; if (in_array($func,$skipFunc)) { break; } $error['line'] = sprintf('%04d',$error['line']);
$show .= ' [Line: ' . $error['line'] . ']' . $file . '(' . $func . ')'; $log .= !empty($log) ? ' -> ' : ''; $log .= $file . ':' . $error['line']; } return array($show,$log); }
/** * 异常处理 * * @static * @access public * @param mixed $exception */ public static function exceptionError($exception) { if ($exception instanceof DbException) { $type = 'db'; } else { $type = 'system'; } if ($type == 'db') { $errorMsg = '(' . $exception->getCode() . ') '; $errorMsg .= self::sqlClear($exception->getMessage(),$exception->getDbConfig()); if ($exception->getSql()) { $errorMsg .= '$errorMsg .= self::sqlClear($exception->getSql(),$exception->getDbConfig()); $errorMsg .= ''; } } else { $errorMsg = $exception->getMessage(); } $trace = $exception->getTrace(); krsort($trace); $trace[] = array('file' => $exception->getFile(),'line' => $exception->getLine(),'function' => 'break'); $phpMsg = array(); foreach ($trace as $error) { if (!empty($error['function'])) { $fun = ''; if (!empty($error['class'])) { $fun .= $error['class'] . $error['type']; } $fun .= $error['function'] . '('; if (!empty($error['args'])) { $mark = ''; foreach ($error['args'] as $arg) { $fun .= $mark; if (is_array($arg)) { $fun .= 'Array'; } elseif (is_bool($arg)) { $fun .= $arg ? 'true' : 'false'; } elseif (is_int($arg)) { $fun .= (defined('SITE_DEBUG') && SITE_DEBUG) ? $arg : '%d'; } elseif (is_float($arg)) { $fun .= (defined('SITE_DEBUG') && SITE_DEBUG) ? $arg : '%f'; } else { $fun .= (defined('SITE_DEBUG') && SITE_DEBUG) ? ''' . htmlspecialchars(substr(self::clear($arg),10)) . (strlen($arg) > 10 ? ' ...' : '') . ''' : '%s'; } $mark = ','; } } $fun .= ')'; $error['function'] = $fun; } if (!isset($error['line'])) { continue; } $phpMsg[] = array('file' => str_replace(array(SITE_PATH,''),array('','/'),$error['file']),'line' => $error['line'],'function' => $error['function']); } self::showError($type,$errorMsg,$phpMsg); exit(); }
/** * 记录错误日志 * * @static * @access public * @param string $message */ public static function writeErrorLog($message) {
return false; // 暂时不写入
$message = self::clear($message); $time = time(); $file = LOG_PATH . '/' . date('Y.m.d') . '_errorlog.php'; $hash = md5($message);
$userId = 0; $ip = get_client_ip();
$user = 'User: userId=' . intval($userId) . '; IP=' . $ip . '; RIP:' . $_SERVER['REMOTE_ADDR']; $uri = 'Request: ' . htmlspecialchars(self::clear($_SERVER['REQUEST_URI'])); $message = "t{$time}t$messaget$hasht$user $urin";
// 判断该$message是否在时间间隔$maxtime内已记录过,有,则不用再记录了 if (is_file($file)) { $fp = @fopen($file,'rb'); $lastlen = 50000;// 读取最后的 $lastlen 长度字节内容 $maxtime = 60 * 10;// 时间间隔:10分钟 $offset = filesize($file) - $lastlen; if ($offset > 0) { fseek($fp,$offset); } if ($data = fread($fp,$lastlen)) { $array = explode("n",$data); if (is_array($array)) foreach ($array as $key => $val) { $row = explode("t",$val); if ($row[0] != '') { continue; } if ($row[3] == $hash && ($row[1] > $time - $maxtime)) { return; } } } }
error_log($message,3,$file); }
/** * 清除文本部分字符 * * @param string $message */ public static function clear($message) { return str_replace(array("t","r","n")," ",$message); }
/** * sql语句字符清理 * * @static * @access public * @param string $message * @param string $dbConfig */ public static function sqlClear($message,$dbConfig) { $message = self::clear($message); if (!(defined('SITE_DEBUG') && SITE_DEBUG)) { $message = str_replace($dbConfig['database'],'***',$message); //$message = str_replace($dbConfig['prefix'],$message); $message = str_replace(C('DB_PREFIX'),$message); } $message = htmlspecialchars($message); return $message; }
/** * 显示错误 * * @static * @access public * @param string $type 错误类型 db,system * @param string $errorMsg * @param string $phpMsg */ public static function showError($type,$phpMsg = '') { global $_G;
$errorMsg = str_replace(SITE_PATH,$errorMsg); ob_end_clean(); $host = $_SERVER['HTTP_HOST']; $title = $type == 'db' ? 'Database' : 'System'; echo <<
$host - $title Error
$title Error $errorMsg EOT; if (!empty($phpMsg)) { echo 'echo 'PHP Debug '; echo ''; if (is_array($phpMsg)) { echo 'foreach ($phpMsg as $k => $msg) { $k++; echo ' echo 'echo ' | echo ' | echo ' | echo ' | } } else { echo '' . $phpMsg . '} echo ' } echo <<
EOT; exit(); } }
/** * DB异常类 * * @author blog.snsgou.com */ class DbException extends Exception {
protected $sql; protected $dbConfig;// 当前数据库配置信息
public function __construct($message,$code = 0,$sql = '',$dbConfig = array()) { $this->sql = $sql; $this->dbConfig = $dbConfig; parent::__construct($message,$code); }
public function getSql() { return $this->sql; }
public function getDbConfig() { return $this->dbConfig; } } (编辑:安卓应用网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|