php中有三个函数与捕捉运行错误有关,分别是:

set_error_handler:运行错误处理函数,php内核执行代码出错时一般是触发error,而不是抛异常,抛异常是面向对象编程中用的

set_exception_handler:运行异常信息处理函数,当代码中throw的异常没有被try-catch捕获时,就会调用该函数。php中error和exception的区别可以看这篇回答:php-exceptions-vs-errors

register_shutdown_function:脚本关闭执行函数,会在php脚本每次执行完成退出前运行。

为了保证运行错误能被顺利捕捉到,必须保证在有错的程序执行前先注册了错误处理函数。 一般错误处理代码结构如下:

function handle_normal_error($errno, $errstr,  $errfile, $errline)
{
    // 把error封装为异常,由异常处理函数统一处理
	throw new ErrorException($errstr, 0, $errno, $errfile, $errline);

	// don't execute php default exception action
	return true;
}
set_error_handler('handle_normal_error', E_ALL | E_STRICT);


function user_exception_handler($ex)
{
    switch ($errno)
	{
		case E_USER_ERROR:
			send_error_to_log_server($msg);
			break;
		case E_USER_WARNING:
			// do something
			break;
		default:
			// do something
			break;
	}
}
set_exception_handler('user_exception_handler');


function handle_fatal_error()
{
	$error = error_get_last();
	if (isset($error['type']) && E_ERROR == $error['type']) {
		send_error_to_log_server($msg);
	}
}
register_shutdown_function('handle_fatal_error');

在thinkphp 3.13中,已经做了全局导常处理,代码如下: {% codeblock Think.class.php %}

/** * 应用程序初始化 * @access public * @return void */ static public function start() { // 设定错误和异常处理 register_shutdown_function(array(‘Think’,‘fatalError’)); set_error_handler(array(‘Think’,‘appError’)); set_exception_handler(array(‘Think’,‘appException’));

    ...
}

/** * 自定义异常处理 * @access public * @param mixed $e 异常对象 */ static public function appException($e) { $error = array(); $error[‘message’] = $e->getMessage(); $trace = $e->getTrace(); if(‘throw_exception'==$trace[0][‘function’]) { $error[‘file’] = $trace[0][‘file’]; $error[‘line’] = $trace[0][‘line’]; }else{ $error[‘file’] = $e->getFile(); $error[‘line’] = $e->getLine(); } Log::record($error[‘message’],Log::ERR); halt($error); }

/**
 * 自定义错误处理
 * @access public
 * @param int $errno 错误类型
 * @param string $errstr 错误信息
 * @param string $errfile 错误文件
 * @param int $errline 错误行数
 * @return void
 */
static public function appError($errno, $errstr, $errfile, $errline) {
  switch ($errno) {
      case E_ERROR:
      case E_PARSE:
      case E_CORE_ERROR:
      case E_COMPILE_ERROR:
      case E_USER_ERROR:
        ob_end_clean();
        // 页面压缩输出支持
        if(C('OUTPUT_ENCODE')){
            $zlib = ini_get('zlib.output_compression');
            if(empty($zlib)) ob_start('ob_gzhandler');
        }
        $errorStr = "$errstr ".$errfile." 第 $errline 行.";
        if(C('LOG_RECORD')) Log::write("[$errno] ".$errorStr,Log::ERR);
        function_exists('halt')?halt($errorStr):exit('ERROR:'.$errorStr);
        break;
      case E_STRICT:
      case E_USER_WARNING:
      case E_USER_NOTICE:
      default:
        $errorStr = "[$errno] $errstr ".$errfile." 第 $errline 行.";
        trace($errorStr,'','NOTIC');
        break;
  }
}

// 致命错误捕获
static public function fatalError() {
    // 保存日志记录
    if(C('LOG_RECORD')) Log::save();
    if ($e = error_get_last()) {
        switch($e['type']){
          case E_ERROR:
          case E_PARSE:
          case E_CORE_ERROR:
          case E_COMPILE_ERROR:
          case E_USER_ERROR:
            ob_end_clean();
            function_exists('halt')?halt($e):exit('ERROR:'.$e['message']. ' in <b>'.$e['file'].'</b> on line <b>'.$e['line'].'</b>');
            break;
        }
    }
}

{% endcodeblock %}

{% codeblock functions.php %}

/**

  • 错误输出
  • @param mixed $error 错误
  • @return void */ function halt($error) { $e = array(); if (APP_DEBUG) { //调试模式下输出错误信息 if (!is_array($error)) { $trace = debug_backtrace(); $e[‘message’] = $error; $e[‘file’] = $trace[0][‘file’]; $e[‘line’] = $trace[0][‘line’]; ob_start(); debug_print_backtrace(); $e[‘trace’] = ob_get_clean(); } else { $e = $error; } } else { //否则定向到错误页面 $error_page = C(‘ERROR_PAGE’); if (!empty($error_page)) { redirect($error_page); } else { if (C(‘SHOW_ERROR_MSG’)) $e[‘message’] = is_array($error) ? $error[‘message’] : $error; else $e[‘message’] = C(‘ERROR_MESSAGE’); } } // 包含异常页面模板 include C(‘TMPL_EXCEPTION_FILE’); exit; }

{% endcodeblock %}