laravel返回統一格式錯誤碼

背景

最近在學習開發一個安卓項目,後端接口項目開始用PHP的Yii2.0框架新啓了個項目,後換成laravel5.5,最近看到laravel升級了新版本,因而又將項目更新到laravel6.4
在使用yii和laravel的過程當中,兩個框架對web-api都很是友好,也都對restful作了不一樣程度的支持,可是仍是遇到了一些問題,下面以laravel6.4爲例,簡單描述下我遇到的問題。php

問題一:訪問接口返回頁面代碼

最典型的就是laravel new 一個項目後,在瀏覽器直接訪問localhost會進入laravel框架模版的默認歡迎頁,這個沒有太大的問題,問題就是你用postman把這個地址當接口
調用,返回的就是頁面的代碼,你在安卓端調用返回的仍是頁面的代碼,其實實際使用不會去調用/跟接口,可是調用接口的時候一些其餘的錯誤好比4xx,5xx都會返回html代碼。
安卓端只能經過判斷狀態碼來判斷請求的成功失敗,並且極難拿到錯誤信息。其實這裏能夠在安卓端統一加header,可是...... 因而網上查了下怎麼處理
第一種辦法解決postman調試的是能夠在postman的請求中設置headers X-Requested-With:XMLHttpRequest來模擬ajax請求
第二種辦法使項目僅返回JSON格式的須要新建一個Middlewarehtml

namespace App\Http\Middleware;
use Closure;
class JsonApplication
{
    public function handle($request, Closure $next)
    {
        $request->headers->set('Accept', 'application/json');
        return $next($request);
    }
}

而後在Kernel中全局註冊Middleware並應用全部的api請求(這裏由於項目是web-api項目,因此將routes/api.php的namespace去掉了,因此$middlewareGroups中的key是api)vue

namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
    protected $middlewareGroups = [
        'api' => [
            ......
            'json_application',
        ],
    ];
    protected $routeMiddleware = [
        ......
        'json_application' => \App\Http\Middleware\JsonApplication::class,
    ];
}

這樣配置好後就不再用擔憂調用接口,給你返回的是頁面代碼。java

問題二: 接口返回統一的JSON格式

經過上面的配置接口返回數據都是JSON的格式了,可是繼續開發會發現,仍是須要經過HTTP狀態碼來判斷是否成功,而後返回的JSON裏面的key不一樣的接口差別特別大,即便同一個接口在成功和出錯的時候也會返回不一樣的KEY。
這個問題多采用返回同一格式的問題,因爲以前給vue寫過不少接口,因此仍是沿用以前的key的模式laravel

{
    "code": "0",
    "msg": "ok",
    "data": ""
}

可是在laravel中怎麼返回這個格式成了一個問題,網上查了好幾回,都沒有太好的解決辦法,可能是覆蓋的狀況不全,再有就是錯誤碼錯誤信息都寫在邏輯層,新加的徹底不知道有沒有衝突。
後來又在BD和GG搜索很久,本身也嘗試用laravel自帶的異常機制和Middleware處理,始終不是太滿意。
用過JAVA的都知道,在java中處理錯誤碼很方便,直接定義一個枚舉把全部的錯誤代碼都寫在裏面,拋出異常的時候枚舉當作參數傳遞進去。相似於這樣
枚舉git

package *.*.*
public enum ErrorCode {
    OK("ok", 0),
    PARAM_ERROR("param error", 88888),
    UNKNOWN_ERROR("unknown error", 99999);
    ErrorCode(String value, Integer key) {
        this.value = value;
        this.key = key;
    }
    private String value;
    private Integer key;
    public String getValue() {
        return value;
    }
    public Integer getKey() {
        return key;
    }
}

異常類github

package *.*.*;
import *.*.*.ErrorCode;
public class ApiException extends Exception {
    public int code = 0;
    public ApiException(ErrorCode errorCode) {
        super(errorCode.getValue());
        this.code = errorCode.getKey();
    }
    ......
}

使用web

throw new ApiException(ErrorCode.UNKNOWN_ERROR);

因而查了下PHP的枚舉,還真支持,但仔細一研究才發現,PHP的枚舉不只要安裝開啓SPL,然而提供的方法也並無什麼卵用
因而仿照JAVA寫了一個
基類ajax

namespace App\Enums;
abstract class Enum
{
    public static function __callStatic($name, $arguments)
    {
        return new static(constant('static::' . $name));
    }
}

錯誤碼 這裏由於用到了魔術方法,因此要在注視中標註json

namespace App\Enums;
/**
 * @method static CodeEnum OK
 * @method static CodeEnum ERROR
 */
class CodeEnum extends Enum
{
    public const OK = ['0', 'ok'];
    public const ERROR = ['99999', 'fail'];
    private $code;
    private $msg;
    public function __construct($param)
    {
        $this->code = reset($param);
        $this->msg = end($param);
    }
    public function getCode()
    {
        return $this->code;
    }
    public function getMsg()
    {
        return $this->msg;
    }
}

自定義異常類

namespace App\Exceptions;
use App\Enums\CodeEnum;
use Exception;
use Illuminate\Support\Facades\Log;
class ApiException extends Exception
{
    public function __construct(CodeEnum $enum)
    {
        parent::__construct($enum->getMsg(), $enum->getCode());
    }
    public function render($request)
    {
        return response([
            'code' => $this->getCode(),
            'msg' => $this->getMessage(),
            'data' => ''
        ]);
    }
}

調用

throw new ApiException(new CodeEnum(CodeEnum::ERROR)); // 這樣調總感受不太好看
throw new ApiException(CodeEnum::OK()); // 這樣調用和java的調用方式就很像了

固然可能有人以爲你寫的是php,爲何總也和java比呢,這裏沒有比的意思,本人因爲工做須要在平時工做中java和php都寫,會結合另外一種語言好的用法來使用。php中好的用法也會想着如何用java來實現。

上面的實現已經將源碼放到github上了

https://github.com/yinfuyuan/php-enum

詳細的使用方法也能夠參考另外一篇文章

https://segmentfault.com/a/1190000022711880

在文末介紹了枚舉結合laravel返回統一格式錯誤碼的用法

相關文章
相關標籤/搜索