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