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


Posted in PHP onNovember 04, 2019

背景

最近在学习开发一个安卓项目,后端接口项目开始用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

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)

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,
  ];
}

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

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

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

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

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

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

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

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

枚举

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;
  }
}

异常类

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

使用

throw new ApiException(ErrorCode.UNKNOWN_ERROR);

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

于是仿照JAVA写了一个

基类

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

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

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 report()
  {
    Log::error("ApiException {$this->getFile()}({$this->getLine()}): code({$this->getCode()}) msg({$this->getMessage()})");
  }
  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的调用方式就很像了

总结

以上所述是小编给大家介绍的laravel返回统一格式错误码问题,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

PHP 相关文章推荐
PHP安全编程之加密功能
Oct 09 PHP
实现 win2003 下 mysql 数据库每天自动备份
Dec 06 PHP
php+mysql开源XNA 聚合程序发布 下载
Jul 13 PHP
php 获取select下拉列表框的值
May 08 PHP
PHP isset()与empty()的使用区别详解
Aug 29 PHP
php实现无限级分类实现代码(递归方法)
Jan 01 PHP
array_multisort实现PHP多维数组排序示例讲解
Jan 04 PHP
Yii Framework框架获取分类下面的所有子类方法
Jun 20 PHP
php计算多维数组中所有值总和的方法
Jun 24 PHP
Linux系统中设置多版本PHP共存配合Nginx服务器使用
Dec 21 PHP
PHP在弹框中获取foreach中遍历的id值并传递给地址栏
Jun 13 PHP
Yii2框架数据验证操作实例详解
May 02 PHP
php 中self,this的区别和操作方法实例分析
Nov 04 #PHP
PHP 文件写入和读取操作实例详解【必看篇】
Nov 04 #PHP
PHP连接MySQL数据库的三种方式实例分析【mysql、mysqli、pdo】
Nov 04 #PHP
php ZipArchive实现多文件打包下载实例
Oct 31 #PHP
Laravel框架实现抢红包功能示例
Oct 31 #PHP
laravel框架实现后台登录、退出功能示例
Oct 31 #PHP
TP5框架简单登录功能实现方法示例
Oct 31 #PHP
You might like
smarty 原来也不过如此~~呵呵
2006/11/25 PHP
很让人受教的 提高php代码质量36计
2012/09/05 PHP
PHP 使用MySQL管理Session的回调函数详解
2013/06/21 PHP
学习php设计模式 php实现原型模式(prototype)
2015/12/07 PHP
PHP有序表查找之二分查找(折半查找)算法示例
2018/02/09 PHP
php项目中类的自动加载实例讲解
2019/09/12 PHP
传智播客学习之JavaScript基础篇
2009/11/13 Javascript
JS DOM 操作实现代码
2010/08/01 Javascript
jQuery图片滚动图片的效果(另类实现)
2013/06/02 Javascript
Javascript获取当前日期的农历日期代码
2014/10/08 Javascript
jquery实现Slide Out Navigation滑出式菜单效果代码
2015/09/07 Javascript
js实现n秒倒计时后才可以点击的效果
2015/12/20 Javascript
记录一篇关于redux-saga的基本使用过程
2018/08/18 Javascript
vue router 跳转后回到顶部的实例
2018/08/31 Javascript
Element InputNumber 计数器的实现示例
2020/08/03 Javascript
vue 动态给每个页面添加title、关键词和描述的方法
2020/08/28 Javascript
多个Vue项目部署到服务器的步骤记录
2020/10/22 Javascript
[03:18]DOTA2亚洲邀请赛小组赛第一日 RECAP赛事回顾
2015/01/30 DOTA
[42:11]TNC vs Pain 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/20 DOTA
python操作CouchDB的方法
2014/10/08 Python
Python和C/C++交互的几种方法总结
2017/05/11 Python
Python数据结构与算法之列表(链表,linked list)简单实现
2017/10/30 Python
python实现猜数字游戏
2020/03/25 Python
PYTHON如何读取和写入EXCEL里面的数据
2019/10/28 Python
python爬虫开发之Beautiful Soup模块从安装到详细使用方法与实例
2020/03/09 Python
解决导入django_filters不成功问题No module named 'django_filter'
2020/07/15 Python
YesStyle美国/全球:购买亚洲时装、美容化妆品和生活百货
2017/01/16 全球购物
Shein英国:女性时尚网上商店
2019/04/10 全球购物
建筑工程技术应届生求职信
2013/11/17 职场文书
成品仓管员工作职责
2013/12/29 职场文书
军训学生自我鉴定
2014/02/12 职场文书
物资采购方案
2014/06/12 职场文书
雷锋式好少年事迹材料
2014/08/17 职场文书
自查自纠整改报告
2014/11/06 职场文书
《艾尔登法环》1.03.3补丁上线 碎星伤害调整
2022/04/07 其他游戏
Linux中如何安装并部署Redis
2022/04/18 Servers