laravel-異常處理
阿新 • • 發佈:2019-01-25
laravel 異常丟擲
在開發中錯誤處理是非常重要的,最重要是兩點:第一,宣告異常的錯誤程式碼和資訊。第二,不同場景下丟擲異常的有所不同,比如 api 中一般是前端 ajax 請求,那麼丟擲的異常應該是 json 形式,如果是開發模式下,頁面中丟擲普通異常,便於程式猿調錯,在生產環境下,則統一將錯誤彙總放入一個錯誤頁面進行渲染。
宣告異常
就以一個使用者模組來舉例:
在 /config/exceptions.php 中宣告丟擲異常的資訊和錯誤程式碼
<?php
return [
'not_found_api' => ['message' => '介面未找到' , 'code' => '404'],
'not_found_page' => ['message' => '頁面未找到', 'code' => '404'],
'user' => [
'already_logout' => ['message' => '您已處於登出狀態,請重新登入', 'code' => '40005'],
'permission_deny' => ['message' => '您無訪問許可權', 'code' => '40001'],
'captcha_error' => ['message' => '簡訊驗證碼錯誤', 'code' => '40002'],
'not_found' => ['message' => '該使用者不存在', 'code' => '40003'],
'not_admin' => ['message' => '該賬號沒有管理後臺許可權!', 'code' => '40004'],
]
];
在 /app/Exceptions/ 下的檔案目錄結構:
app/Exceptions
BaseException.php
User.php
Handler.php
BaseException.php : 接受和處理異常,並傳入父類的建構函式異常處理中
<?php
namespace App\Exceptions;
use JsonSerializable;
use Exception;
class BaseException extends Exception implements JsonSerializable{
const EXCEPTION_CONFIG_PREFIX = 'exceptions.';
public function __construct($config = '', $message = null, $code = null){
$exception = config(static::EXCEPTION_CONFIG_PREFIX.$config);
$code = is_null($code)? $exception['code'] : $code;
$message = is_null($message) ? $exception['message'] : $message;
parent::__construct($message, $code);
}
public function jsonSerialize(){
return [
'errCode' => $this->getCode(),
'message' => $this->getMessage()
];
}
public function setMessage($message){
$this->message = $message;
}
public function setCode($code){
$this->code = $code;
}
}
User.php : 宣告使用者 User 模組中的異常
<?php
namespace App\Exceptions;
class User extends BaseException{
const EXCEPTION_CONFIG_PREFIX = 'exceptions.user.';
}
Handler.php : 處理異常
<?php
namespace App\Exceptions;
use Exception;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Symfony\Component\HttpKernel\Exception\HttpException;
//區別是否 ajax 請求 api 而分別處理的 404 錯誤
use App\Exceptions\NotFoundApi as NotFoundApiException;
use App\Exceptions\NotFoundPage as NotFoundPageException;
//在此名稱空間 /vendor/symfony/http-kernel/Exception 下有許多異常,可以參考一下
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use App\Traits\Response as ResponseTrait;
class Handler extends ExceptionHandler
{
use ResponseTrait;
/**
* A list of the exception types that should not be reported.
*
* @var array
*/
protected $dontReport = [
HttpException::class,
ModelNotFoundException::class,
];
/**
* Report or log an exception.
*
* This is a great spot to send exceptions to Sentry, Bugsnag, etc.
*
* @param \Exception $e
* @return void
*/
public function report(Exception $e)
{
return parent::report($e);
}
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $e
* @return \Illuminate\Http\Response
*/
public function render($request, Exception $e)
{
//如果是生產環境
if (env('APP_DEGUB')) {
$exceptions = [];
$exceptions['code'] = $e->getCode();
$exceptions['message'] = $e->getMessage();
//上線時,需要對丟擲的異常進行彙總互動至前端 view 中
return response()->view("errors.exceptions", ['exceptions' => $exceptions]);
}
if ($e instanceof ModelNotFoundException) {
$e = new NotFoundHttpException($e->getMessage(), $e);
}
/**
* 除錯環境下,不需要返回json格式的結果
*/
if(!env('APP_NEED_JSON_RESPONSE')){
return parent::render($request, $e);
}
if($request->ajax() || $request->wantsJson()){
if($e instanceof NotFoundHttpException){
$e = new NotFoundApiException;
}
return $this->jsonResponse(null, $e->getMessage(), $e->getCode());
}else{
if($e instanceof NotFoundHttpException){
$e = new NotFoundPageException;
}
return parent::render($request, $e);
}
}
}
準備工作都做好後,拋異常就非常簡單了 :
use App\Exceptions\User as UserException;
throw new UserException('captcha_error');