php異常處理以及l(fā)aravel框架自定義異常處理

PHP錯(cuò)誤:是屬于php程序自身的問題,一般是由非法的語法,環(huán)境問題導(dǎo)致的,使得編譯器無法通過檢查,甚至無法運(yùn)行的情況。平時(shí)遇到的warming、notice都是錯(cuò)誤,只是級別不同而已。

Fatal Error:致命錯(cuò)誤(腳本終止運(yùn)行)
        E_ERROR         // 致命的運(yùn)行錯(cuò)誤,錯(cuò)誤無法恢復(fù),暫停執(zhí)行腳本
        E_CORE_ERROR    // PHP啟動(dòng)時(shí)初始化過程中的致命錯(cuò)誤
        E_COMPILE_ERROR // 編譯時(shí)致命性錯(cuò),就像由Zend腳本引擎生成了一個(gè)E_ERROR
        E_USER_ERROR    // 自定義錯(cuò)誤消息。像用PHP函數(shù)trigger_error(錯(cuò)誤類型設(shè)置為:E_USER_ERROR)

    Parse Error:編譯時(shí)解析錯(cuò)誤,語法錯(cuò)誤(腳本終止運(yùn)行)
        E_PARSE  //編譯時(shí)的語法解析錯(cuò)誤

    Warning Error:警告錯(cuò)誤(僅給出提示信息,腳本不終止運(yùn)行)
        E_WARNING         // 運(yùn)行時(shí)警告 (非致命錯(cuò)誤)。
        E_CORE_WARNING    // PHP初始化啟動(dòng)過程中發(fā)生的警告 (非致命錯(cuò)誤) 。
        E_COMPILE_WARNING // 編譯警告
        E_USER_WARNING    // 用戶產(chǎn)生的警告信息

    Notice Error:通知錯(cuò)誤(僅給出通知信息,腳本不終止運(yùn)行)
        E_NOTICE      // 運(yùn)行時(shí)通知。表示腳本遇到可能會(huì)表現(xiàn)為錯(cuò)誤的情況.
        E_USER_NOTICE // 用戶產(chǎn)生的通知信息。

PHP異常:一般是業(yè)務(wù)邏輯上出現(xiàn)的不合預(yù)期、與正常流程不同的狀況,不是語法錯(cuò)誤。
異常處理用于在指定的錯(cuò)誤(異常)情況發(fā)生時(shí)改變腳本的正常流程,我們可以使用set_error_handler函數(shù)設(shè)置用戶自定義的錯(cuò)誤處理函數(shù)來處理錯(cuò)誤,set_exception_handler函數(shù)設(shè)置用戶自定義的異常處理函數(shù)來處理異常。例如我們想把異常和錯(cuò)誤都處理成json格式輸出和調(diào)試,代碼如下:

function ErrorHandler($error_level,$error_message,
                      $error_file,$error_line,$error_request)
{
    $httpVersion = "HTTP/1.1";
    $contentType = 'application/json';
    header($httpVersion. " ". 500 ." ". $error_message);
    header("Content-Type:". $contentType);
    echo json_encode(['message'=>$error_message,'file'=>$error_file,'line'=>$error_line]);die();
}

function ExceptionHandler($exception)
{
    $httpVersion = "HTTP/1.1";
    $contentType = 'application/json';
    header($httpVersion. " ". $exception->getCode() ." ". "Bad Request");
    header("Content-Type:". $contentType);
    echo json_encode(['message'=>$exception->getMessage(),'file'=>$exception->getFile(),'line'=>$exception->getLine()]);die();
}

set_error_handler("ErrorHandler");
set_exception_handler('ExceptionHandler');

$a = 1/0;//測試錯(cuò)誤
throw new Exception('Uncaught Exception');//測試異常

有時(shí)候我們用laravel寫api接口的時(shí)候代碼不嚴(yán)謹(jǐn)導(dǎo)致報(bào)錯(cuò),接口直接返回一個(gè)渲染地十分漂亮的html網(wǎng)頁,這時(shí)候前端就無法解析了,app甚至可能直接崩潰,這樣并不好,我們希望的是不管發(fā)生什么情況都返回統(tǒng)一格式的json,好統(tǒng)一處理。
接下來講如何應(yīng)用到laravel框架中去,最先想到的是寫一個(gè)中間件,把set_error_handler("ErrorHandler")和
set_exception_handler('ExceptionHandler')方法放進(jìn)去,然后把上述兩個(gè)自定義方法全局加載。然后只要用到這個(gè)中間件的路由就可以像上述那樣將錯(cuò)誤和異常處理成統(tǒng)一的json格式輸出。但是卻發(fā)現(xiàn)除了錯(cuò)誤能被捕獲,其他的都無法捕獲。于是我決定去App\Exceptions\Handler類動(dòng)下手腳。laravel所有異常和錯(cuò)誤都由類 App\Exceptions\Handler 處理,該類包含兩個(gè)方法:report 和 render,report 方法只是將異常傳遞給異常被記錄的基類,我們可以在這個(gè)方法下面自定義我們的錯(cuò)誤處理方法。

class ExceptionHandler
{
    static $httpVersion = "HTTP/1.1";
    static $contentType = 'application/json';
    public static function getHttpStatusMessage($statusCode){
        $httpStatus = array(
            100 => 'Continue',
            101 => 'Switching Protocols',
            200 => 'OK',
            201 => 'Created',
            202 => 'Accepted',
            203 => 'Non-Authoritative Information',
            204 => 'No Content',
            205 => 'Reset Content',
            206 => 'Partial Content',
            300 => 'Multiple Choices',
            301 => 'Moved Permanently',
            302 => 'Found',
            303 => 'See Other',
            304 => 'Not Modified',
            305 => 'Use Proxy',
            306 => '(Unused)',
            307 => 'Temporary Redirect',
            400 => 'Bad Request',
            401 => 'Unauthorized',
            402 => 'Payment Required',
            403 => 'Forbidden',
            404 => 'Not Found',
            405 => 'Method Not Allowed',
            406 => 'Not Acceptable',
            407 => 'Proxy Authentication Required',
            408 => 'Request Timeout',
            409 => 'Conflict',
            410 => 'Gone',
            411 => 'Length Required',
            412 => 'Precondition Failed',
            413 => 'Request Entity Too Large',
            414 => 'Request-URI Too Long',
            415 => 'Unsupported Media Type',
            416 => 'Requested Range Not Satisfiable',
            417 => 'Expectation Failed',
            500 => 'Internal Server Error',
            501 => 'Not Implemented',
            502 => 'Bad Gateway',
            503 => 'Service Unavailable',
            504 => 'Gateway Timeout',
            505 => 'HTTP Version Not Supported');
        return ($httpStatus[$statusCode]) ? $httpStatus[$statusCode] : $httpStatus[500];

    }
public static function exception_handler(\Exception $exception){
        header("Content-Type:". self::$contentType);
        $statusCode = method_exists($exception,'getStatusCode')?$exception->getStatusCode():$exception->getCode();
        header(self::$httpVersion. " ". ($statusCode = $statusCode == 0? 500 : $statusCode) ." " . self::getHttpStatusMessage($statusCode));
        $response = array(
            'data'=>[],
            'status_code'=>$statusCode == 0?500:$statusCode,
            'error_msg'=>$exception->getMessage(),
            'error_code'=>method_exists($exception,'getErrorId')?$exception->getErrorId():self::getHttpStatusMessage($statusCode),
        );
        if (env('APP_DEBUG')){
            $response = array_merge($response,array('debug'=>array(
                'file'=>$exception->getFile(),
                'line'=>$exception->getLine(),
                'trace'=>$exception->getTrace(),
                'type'=>get_class($exception)
            )));
        }
        echo json_encode($response);die();

    }
  
}

然后在report方法引用

   public function report(Exception $exception)
    {
         if (PHP_SAPI == 'cli'){  //判斷是不是cli模式運(yùn)行
            parent::report($exception);
        }else{
            \Linyuee\ExceptionHandler::exception_handler($exception);
        }
    }

這樣異常和錯(cuò)誤都能捕獲處理成json格式了
推介我寫的一個(gè)包,直接comp安裝然后只要像上述那樣在report方法引入就能用了。

composer require linyuee/laravel-exception
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容