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返回统一格式错误码的用法

相关文章
相关标签/搜索