// 自定义异常函数
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 = '<b>' . $message . '</b><br /><b>PHP:</b>' . $logTrace;
self::writeErrorLog($messageSave);
}
if ($show) {
self::showError('system', "<li>$message</li>", $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 .= '<li>[Line: ' . $error['line'] . ']' . $file . '(' . $func . ')</li>';
$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 .= '<div>';
$errorMsg .= self::sqlClear($exception->getSql(), $exception->getDbConfig());
$errorMsg .= '</div>';
}
} 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), 0, 10)) . (strlen($arg) > 10 ? ' ...' : '') . '\'' : '%s';
}
$mark = ', ';
}
}
$fun .= ')';
$error['function'] = $fun;
}
if (!isset($error['line'])) {
continue;
}
$phpMsg[] = array('file' => str_replace(array(SITE_PATH, '\\'), array('', 'https://www.jb51.net/'), $error['file']), 'line' => $error['line'], 'function' => $error['function']);
}
self::showError($type, $errorMsg, $phpMsg);
exit();
}