规范 API 接口错误响应格式

Laravel框架
468
0
0
2022-05-13
标签   Laravel API
废话不多说了,直接上代码。

定义 json 返回数据格式

首先定义一个 trait

app/Responses/ResponseJson.php
<?php
namespace App\Http\Responses;

trait ResponseJson
{
    private function jsonResponse($status, $code, $message, $data, $error)
    {
        $result = [
            'status'  => $status,
            'code'    => $code,
            'message' => $message,
            'data'    => $data,
            'error'  => $error,
        ];
        return response()->json($result);
    }

    public function jsonSuccessData($data)
    {
        return $this->jsonResponse('success', 200, '请求成功', $data, []);
    }

    public function jsonErrorsData($code, $message, $data = [])
    {
        return $this->jsonResponse('fail', $code, '请求失败', $data, $message);
    }
}

统一的数据响应格式,固定包含:codestatusdatamessageerror

  • 成功直接调用 jsonSuccessData方法,传入$data数据;
  • 失败调用 jsonErrorsData 方法,传入 $code$message$data, $data可以为空;

在基类控制器中引用

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Responses\ResponseJson;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;

class Controller extends BaseController
{
    use AuthorizesRequests, DispatchesJobs, ValidatesRequests, ResponseJson;
}

修改 Handler 函数

App\Exceptions\Handler.php
<?php

namespace App\Exceptions;

use Throwable;

use App\Http\Responses\ResponseJson;

use Illuminate\Database\QueryException;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Validation\ValidationException;
use \Symfony\Component\HttpKernel\Exception\HttpException;

use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;

class Handler extends ExceptionHandler
{
    use ResponseJson;

    protected $dontReport = [
        //
    ];

    protected $dontFlash = [
        'current_password',
        'password',
        'password_confirmation',
    ];

    public function register()
    {
        $this->reportable(function (Throwable $e) {
            //
        });
    }

    // 新增以下方法  
    public function render($request, Throwable $e)
    {
        $data = [];

        // 客户端错误  
        if ($e instanceof QueryException) {
            // 数据库错误  
            $code = 500;
            $message = '数据库错误,请联系开发者';
            if (env('APP_DEBUG')) {
                $data = $e->getMessage();
            }

        }  else if ($e instanceof ValidationException) {
            // 验证错误  
            $code = 422;
            $message = '参数格式错误';
            $data = $e->errors();

        }  else if ($e instanceof HttpException) {
            // URL不正确  
            $code = 404;
            $message = '未定义路由,请检查 URL 是否正确';

        }  else if ($e instanceof AuthenticationException) {
            // token异常  
            $code = 403;
            $message = 'token异常,禁止访问';

        } else {
            // 其他异常  
            $code = 500;
            $message = '服务器异常';
            $data = $e->getMessage();
        }

        return $this->jsonErrorsData($code, $message, $data);
    }
}

代码说明:

  1. 首先 use 几个文件:
  • use Illuminate\Database\QueryException;
  • 这是用来捕获数据错误的,例如:数据库连接失败,查询字段不存在等等;
  • use Illuminate\Auth\AuthenticationException;
  • 这是用来捕获身份验证错误的,例如:token过期;
  • use Illuminate\Validation\ValidationException;
  • 这是用来捕获表单验证错误的,例如:参数格式不对、参数缺失等等;
  • use \Symfony\Component\HttpKernel\Exception\HttpException;
  • 这是用来捕获 http 请求异常的,例如:url不存在
备注: 还有一些其他类用来捕获其他类型的异常,请自行查找,以上只列出常用的几种异常捕获
  1. rander函数中,用instanceof方法将$e判断出是哪种错误,然后定义该种错误的状态码,获取到错误信息,然后返回给jsonErrorsData函数;

测试

  • 获取数据列表接口:
  • 成功:
{ 
  "status": "success", 
  "code": 200, 
  "message": "请求成功", 
  "data": { 
      "machine": "全部", 
      "lately": "2021-07-09 15:59:40", 
      "max": "[plc] 两点寻边功能已经激活", 
      "cnc": 0, 
      "plc": 69, 
      "count": 69 
  }, 
  "error": ""
}
  • 失败:
{ 
  "status": "fail", 
  "code": 422, 
  "message": "请求失败", 
  "data": { 
      "machine": [ 
          "设备 只能由字母、数字、短划线(-)和下划线(_)组成。", 
          "设备 不能为空。" 
      ] 
  }, 
  "error": "参数格式错误"
}