经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » PHP » 查看文章
laravel返回统一格式错误码问题
来源:jb51  时间:2019/11/4 12:47:19  对本文有异议

背景

最近在学习开发一个安卓项目,后端接口项目开始用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. {
  5. public function handle($request, Closure $next)
  6. {
  7. $request->headers->set('Accept', 'application/json');
  8. return $next($request);
  9. }
  10. }

然后在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. {
  5. protected $middlewareGroups = [
  6. 'api' => [
  7. ......
  8. 'json_application',
  9. ],
  10. ];
  11. protected $routeMiddleware = [
  12. ......
  13. 'json_application' => \App\Http\Middleware\JsonApplication::class,
  14. ];
  15. }

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

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

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

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

  1. {
  2. "code": "0",
  3. "msg": "ok",
  4. "data": ""
  5. }

但是在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. }
  18. }

异常类

  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. ......
  10. }

使用

  1. throw new ApiException(ErrorCode.UNKNOWN_ERROR);

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

于是仿照JAVA写了一个

基类

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

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

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

自定义异常类

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

调用

  1. throw new ApiException(new CodeEnum(CodeEnum::ERROR)); // 这样调总感觉不太好看
  2. throw new ApiException(CodeEnum::OK()); // 这样调用和java的调用方式就很像了

总结

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

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号