TP5使用API時不可預知的內部異常
- 2019 年 10 月 3 日
- 筆記
最常見的錯誤形式例如 controller不存在或者 action不存在之類的 我們第一時間想到的 就是 使用 try{}catch(){} 來捕獲 例如:
/** * show方法在common里定義過--統一返回介面 * @return array */ public function Test(){ try{ model("asda"); }catch (Exception $e){ return show(0,$e->getMessage(),'',400) } }
但是有的錯誤我們是沒有辦法捕獲到的 會返回如下格式
我們API是沒有辦法識別的 所以遇到這種情況 我們應該怎麼解決呢?
首先 不論什麼框架 他都有自己的 錯誤渲染機制 我們應當找到這個渲染機制 去修改它 TP5框架 在 thinkphp/library/think/exception/Handle.php 中 在這個文件中 有一個 render 方法
/** * Render an exception into an HTTP response. * * @param Exception $e * @return Response */ public function render(Exception $e) { if ($this->render && $this->render instanceof Closure) { $result = call_user_func_array($this->render, [$e]); if ($result) { return $result; } } if ($e instanceof HttpException) { return $this->renderHttpException($e); } else { return $this->convertExceptionToResponse($e); } }
我們需要重寫這個方法 使之返回我們想要json格式數據
新建一個類來繼承Handle類
<?php namespace appcommonlibexception; use thinkexceptionHandle; /** * Created by PhpStorm. * User: Administrator * Date: 2019/8/15 * Time: 11:20 */ class ApiHandleException extends Handle { public $httpCode = 500; public function render(Exception $e){ return show(0,$e->getMessage(),[], $this->httpCode); } }
寫好之後 我們還需要在TP5的配置文件中 修改異常處理類 在applicationconfig.php中 大概163行
'exception_handle' => 'appcommonlibexceptionApiHandleException',
指向我們重構的類
接下來我們再去請求 就會返回我們想要的json格式啦
但是問題隨之而來了 如果我們出現如下程式碼報錯的話 狀態會是 500
public function test(){ $data = [ 'aa' => 1, 'ss' => 2, ]; if($data['ss'] != 1){ exception('你提交的數據有問題'); } }
所以需要我們去創建一個 內部的異常類
<?php /** * Created by PhpStorm. * User: Administrator * Date: 2019/8/15 * Time: 11:36 */ namespace appcommonlibexception; use thinkException; class ApiException extends Exception { public $message = ''; public $httpCode = 500; public $code = 0; public function __construct($message = '' , $httpCode = 0, $code = 0) { $this->httpCode = $httpCode; $this->message = $message; $this->code = $code; } }
創建好了之後 我們需要去修改我們之前創建的 ApiHandleExecption 類
<?php namespace appcommonlibexception; use thinkexceptionHandle; /** * Created by PhpStorm. * User: Administrator * Date: 2019/8/15 * Time: 11:20 */ class ApiHandleException extends Handle { public $httpCode = 500; public function render(Exception $e){ if ($e instanceof ApiException) {
##$e->httpCode 就是ApiException裡面的 $this->httpCode; $this->httpCode = $e->httpCode; } return show(0,$e->getMessage(),[], $this->httpCode); } }
這樣我們的狀態碼也會隨之改變 不過 我們還需要在進一步的 優化 ApiHandleException 類 因為 這樣的異常形式 是給API看的 而我們在開發的時候 是需要渲染錯誤的 所以我們修改一下程式碼
<?php namespace appcommonlibexecption; use thinkConfig; use thinkexceptionHandle; /** * Created by PhpStorm. * User: Administrator * Date: 2019/8/15 * Time: 11:20 */ class ApiHandleExecption extends Handle { public $httpCode = 500; public function render(Exception $e){
##判斷debug模式是否開啟 如果開啟 用他父級的 render方法 進行異常渲染 if(config('app_debug') == true){ return parent::render($e); } if ($e instanceof ApiException) { $this->httpCode = $e->httpCode; } return show(0,$e->getMessage(),[], $this->httpCode); } }
至此我們的 內部異常就解決了 梳理下流程 :
首先我們需要 找到 內部異常渲染類(ApiHandleException) 重構它的render方法 重構之後 我們需要進一步的 更改狀態碼 所以需要新建 一個 類(ApiException)來初始化他們的狀態碼等數據 初始化之後 我們還需要進一步修改我們自己寫的異常渲染類(ApiHandleException) 使之在debug模式下 可以正常渲染