CodeIgniter3.0+框架自定義異常處理實現

背景

ci3.0框架核心代碼自動實現了異常,並實現了拋出的對應頁面和方法,對於一些個性化需求特別是接口類型的應用,會不合適。所以須要在不改版核心代碼 (system目錄下文件),來改變對異常及404等相關異常的處理。php

方法說明

ci框架3.0比2.0有比較大的改動,其中之一就是對異常的處理。如下是CodeIgniter-3.1.8\system\core\CodeIgniter.php 中對異常處理的部分代碼redis

/*
 * ------------------------------------------------------
 *  Define a custom error handler so we can log PHP errors
 * ------------------------------------------------------
 */
    set_error_handler('_error_handler');
    set_exception_handler('_exception_handler');
    register_shutdown_function('_shutdown_handler');
...

以上括號內的方法均在common.php中以function_exists爲前提聲明。json

...
if ( ! function_exists('_exception_handler'))
{
...

代碼實現

咱們簡單粗暴的在項目入口文件index.php中重寫如下方法框架

/**
 * 推送到redis cc異常隊列
 * @time 2019/3/21 15:29
 * @author tongbo
 * @param $msg
 * @param $error_type
 * @param $error_code
 * @return bool|int|string
 */
function redis_list_add($msg, $error_type, $error_code)
{
    ini_set('default_socket_timeout', -1);
    $v = explode(':', $_SERVER['SITE_REDIS_SERVER']);
    if (is_array($v) && !empty($v)) {
        try {
            $redis = new redis();
            $redis->pconnect($v[0], $v[1]);
            $space = "\n\n";
            $trace = "";
            if ($error_code) {
                $trace .= "狀態碼    :" . $error_code . "\n";
            }
            if ($error_type) {
                $trace .= "錯誤類型 :" . $error_type . "\n";
            }
            $trace .= "客戶端IP : " . $_SERVER['REMOTE_ADDR'] . "\n";
            $trace .= "服務端IP : " . $_SERVER['SERVER_NAME'] . "(" . $_SERVER['SERVER_ADDR'] . ")" . "\n";
            $trace .= "請求地址 : " . (isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : "empty") . "\n";
            $trace .= "請求參數 : =" . print_r($_REQUEST ? $_REQUEST : $_GET, true) . "\n";
            return $redis->LPUSH('CC_PHP_ERROR_WARNING', $space . $msg . $space . $trace);
        } catch (Exception $e) {
            return $e->getMessage();
        }
    }
}

/**
 * 優先重寫common.php中對應方法
 * 捕捉語法錯誤
 * @time 2019/3/21 16:19
 * @author tongbo
 * @param $severity
 * @param $message
 * @param $filepath
 * @param $line
 */
function _error_handler($severity, $message, $filepath, $line)
{
    $is_error = (((E_ERROR | E_PARSE | E_COMPILE_ERROR | E_CORE_ERROR | E_USER_ERROR | E_STRICT) & $severity) === $severity);

    if ($is_error) {
        $error_msg = $message . "\n" . $filepath . "\n" . $line;
        $error_code = "501";
        redis_list_add($error_msg, 'Error_Handler異常', $error_code);
        exit(json_encode(['success' => '-1', 'code' => $error_code, 'msg' => 'error']));
    }
}

/**
 * 捕獲php自己語法,對象調用,參數類型傳遞等錯誤
 * 優先重寫common.php中對應方法
 * ParseError,object(Error),TypeError,Error
 * @time 2019/3/20 18:33
 * @author tongbo
 * @param $exception
 */
function _exception_handler($exception)
{
    if (!empty($exception)) {
        $error_type = get_class($exception);
        $error_msg = "
錯誤類型:  {$error_type};
文件名:  {$exception->getFile()}; 
所在行號:  {$exception->getLine()}; 
錯誤消息:  {$exception->getMessage()}; ";

        $error_code = "502";
        redis_list_add($error_msg, $error_type, $error_code);
        exit(json_encode(['success' => '-1', 'code' => $error_code, 'msg' => 'exception']));
    }
}

/**
 * 優先重寫common.php中對應方法
 * require_once('no_exists.php')
 * @time 2019/3/21 9:49
 * @author tongbo
 */
function _shutdown_handler()
{
    $last_error = error_get_last();
    if (isset($last_error) &&
        ($last_error['type'] & (E_ERROR | E_PARSE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING))) {
        $error_msg = "
錯誤類型:  shutdown; >
文件名:  {$last_error['file']}; 
所在行號:  {$last_error['line']}; 
錯誤消息:  {$last_error['message']}; ";
        $error_code = "503";
        redis_list_add($error_msg, 'Shut_Down異常', $error_code);
        exit(json_encode(['success' => '-1', 'code' => $error_code, 'msg' => 'shutdown']));
    }
}

/**
 * 優先重寫common.php中對應方法
 * ci 框架內部的load異常、config異常、loader異常等會自動拋出,
 * 但common.php中的函數定義之類錯誤沒法捕捉
 * @time 2019/3/20 18:46
 * @author tongbo
 * @param $message
 * @param int $status_code
 */
function show_error($message)
{
    $error_msg = "錯誤消息:  {$message}; ";
    $error_code = "504";
    redis_list_add($error_msg, '框架加載異常', $error_code);
    exit(json_encode(['success' => '-1', 'code' => $error_code, 'msg' => 'ci_exception_1']));
}

/**
 * 優先重寫common.php中對應方法
 * @time 2019/3/21 15:34
 * @author tongbo
 * @param string $page
 */
function show_404($page = '')
{
    $error_msg = "錯誤消息: 請求的URL: " . $page . " 404 not found";
    $error_code = "404";
    redis_list_add($error_msg, '文件不存在', $error_code);
    exit(json_encode(['success' => '-1', 'code' => $error_code, 'msg' => 'Not Found']));
}

延伸

  1. 在基類中能夠處理
  2. 錯誤等級區分對待
  3. 將錯誤處理寫到其餘地方,require_once進來
相關文章
相關標籤/搜索