当前位置:首页 > CMS教程 > 其它CMS > 列表

laravel返回统一格式错误码问题

发布:smiling 来源: PHP粉丝网  添加日期:2022-01-20 20:26:11 浏览: 评论:0 

在使用yii和laravel的过程中,两个框架对web-api都非常友好,也都对restful做了不同程度的支持,但是还是遇到了一些问题,下面以laravel6.4为例,简单描述下我遇到的问题,需要的朋友参考下吧。

背景

最近在学习开发一个安卓项目,后端接口项目开始用PHP的Yii2.0框架新启了个项目,后换成laravel5.5,最近看到laravel升级了新版本,于是又将项目更新到laravel6.4

在使用yii和laravel的过程中,两个框架对web-api都非常友好,也都对restful做了不同程度的支持,但是还是遇到了一些问题,下面以laravel6.4为例,简单描述下我遇到的问题。

问题一:访问接口返回页面代码

最典型的就是laravel new 一个项目后,在浏览器直接访问localhost会进入laravel框架模版的默认欢迎页,这个没有太大的问题,问题就是你用postman把这个地址当接口

调用,返回的就是页面的代码,你在安卓端调用返回的还是页面的代码,其实实际使用不会去调用/跟接口,但是调用接口的时候一些其他的错误比如4xx,5xx都会返回html代码。

安卓端只能通过判断状态码来判断请求的成功失败,而且极难拿到错误信息。其实这里可以在安卓端统一加header,但是...... 于是网上查了下怎么处理

第一种办法解决postman调试的是可以在postman的请求中设置headers X-Requested-With:XMLHttpRequest来模拟ajax请求

第二种办法使项目仅返回JSON格式的需要新建一个Middleware

  1. namespace App\Http\Middleware; 
  2. use Closure; 
  3. class JsonApplication 
  4.   public function handle($request, Closure $next
  5.   { 
  6.     $request->headers->set('Accept''application/json'); 
  7.     return $next($request); 
  8.   } 

然后在Kernel中全局注册Middleware并应用所有的api请求(这里因为项目是web-api项目,所以将routes/api.php的namespace去掉了,所以$middlewareGroups中的key是api)

  1. namespace App\Http; 
  2. use Illuminate\Foundation\Http\Kernel as HttpKernel; 
  3. class Kernel extends HttpKernel 
  4.   protected $middlewareGroups = [ 
  5.     'api' => [ 
  6.       ...... 
  7.       'json_application'
  8.     ], 
  9.   ]; 
  10.   protected $routeMiddleware = [ 
  11.     ...... 
  12.     'json_application' => \App\Http\Middleware\JsonApplication::class
  13.   ]; 

这样配置好后就再也不用担心调用接口,给你返回的是页面代码。

问题二: 接口返回统一的JSON格式

通过上面的配置接口返回数据都是JSON的格式了,但是继续开发会发现,还是需要通过HTTP状态码来判断是否成功,然后返回的JSON里面的key不同的接口差异特别大,即使同一个接口在成功和出错的时候也会返回不同的KEY。

这个问题多采用返回同一格式的问题,由于之前给vue写过很多接口,所以还是沿用之前的key的模式

  1.   "code": "0", 
  2.   "msg": "ok", 
  3.   "data": "" 

但是在laravel中怎么返回这个格式成了一个问题,网上查了好几次,都没有太好的解决办法,多是覆盖的情况不全,再有就是错误码错误信息都写在逻辑层,新加的完全不知道有没有冲突。

后来又在BD和GG搜索好久,自己也尝试用laravel自带的异常机制和Middleware处理,始终不是太满意。

用过JAVA的都知道,在java中处理错误码很方便,直接定义一个枚举把所有的错误代码都写在里面,抛出异常的时候枚举当做参数传递进去。类似于这样

枚举

  1. package *.*.* 
  2. public enum ErrorCode { 
  3.   OK("ok", 0), 
  4.   PARAM_ERROR("param error", 88888), 
  5.   UNKNOWN_ERROR("unknown error", 99999); 
  6.   ErrorCode(String value, Integer key) { 
  7.     this.value = value; 
  8.     this.key = key; 
  9.   } 
  10.   private String value; 
  11.   private Integer key; 
  12.   public String getValue() { 
  13.     return value; 
  14.   } 
  15.   public Integer getKey() { 
  16.     return key; 
  17.   } 

异常类

  1. package *.*.*; 
  2. import *.*.*.ErrorCode; 
  3. public class ApiException extends Exception { 
  4.   public int code = 0; 
  5.   public ApiException(ErrorCode errorCode) { 
  6.     super(errorCode.getValue()); 
  7.     this.code = errorCode.getKey(); 
  8.   } 
  9.   ...... 

使用

throw new ApiException(ErrorCode.UNKNOWN_ERROR);

于是查了下PHP的枚举,还真支持,但仔细一研究才发现,PHP的枚举不仅要安装开启SPL,然而提供的方法也并没有什么卵用

于是仿照JAVA写了一个

基类

  1. namespace App\Enums; 
  2. abstract class Enum 
  3.   public static function __callStatic($name$arguments
  4.   { 
  5.     return new static(constant('static::' . $name)); 
  6.   } 

错误码 这里因为用到了魔术方法,所以要在注视中标注

  1. namespace App\Enums; 
  2. /** 
  3.  * @method static CodeEnum OK 
  4.  * @method static CodeEnum ERROR 
  5.  */ 
  6. class CodeEnum extends Enum 
  7.   public const OK = ['0''ok']; 
  8.   public const ERROR = ['99999''fail']; 
  9.   private $code
  10.   private $msg
  11.   public function __construct($param
  12.   { 
  13.     $this->code = reset($param); 
  14.     $this->msg = end($param); 
  15.   } 
  16.   public function getCode() 
  17.   { 
  18.     return $this->code; 
  19.   } 
  20.   public function getMsg() 
  21.   { 
  22.     return $this->msg; 
  23.   } 

自定义异常类

  1. namespace App\Exceptions; 
  2. use App\Enums\CodeEnum; 
  3. use Exception; 
  4. use Illuminate\Support\Facades\Log; 
  5. class ApiException extends Exception 
  6.   public function __construct(CodeEnum $enum
  7.   { 
  8.     parent::__construct($enum->getMsg(), $enum->getCode()); 
  9.   } 
  10.   public function report() 
  11.   { 
  12.     Log::error("ApiException {$this->getFile()}({$this->getLine()}): code({$this->getCode()}) msg({$this->getMessage()})"); 
  13.   } 
  14.   public function render($request
  15.   { 
  16.     return response([ 
  17.       'code' => $this->getCode(), 
  18.       'msg' => $this->getMessage(), 
  19.       'data' => '' 
  20.     ]); 
  21.   } 

调用

throw new ApiException(new CodeEnum(CodeEnum::ERROR)); // 这样调总感觉不太好看

throw new ApiException(CodeEnum::OK()); // 这样调用和java的调用方式就很像了

Tags: laravel返回格式错误码

分享到: