异常处理

1. 前言

本小节主要介绍如何处理异常错误情况,正确处理异常可以让接口更加友好,如出现报错,通常会出现 500 错误,异常处理之后可以返回 200,错误内容只需在返回数据中体现。如返回数据中定义 code 字段,然后 code字段不同的值就是告诉接口使用者发生了什么类型的错误,比如 code=401 表示权限不足,code=500表示后端代码层面内部错误,这样就可以更友好的提示用户使用。

2. 定义路由

下面给出异常捕获测试的路由定义如下:

//异常捕获测试
Route::get('exception-test','app\controller\Study\ExceptionController@testException');

如下图所示:
图片描述

3. 定义路由指定的控制器和方法

app\controller\Study 中新建 ExceptionController 控制器和 testException 方法:

<?php
namespace app\controller\Study;
use app\BaseController;
use app\Service\StudentService;
use think\facade\Log;

class ExceptionController extends BaseController
{
    public function testException()
    {
        try{
            $studentService = new StudentService();
            $studentService->update();
        }catch(\Exception $exception){
            Log::write($exception->getMessage(),'test');
            return json("内部错误:".$exception->getMessage());
        }
        return json("请求成功");
    }
}

如下图所示:
图片描述

其中 StudentService 类的定义代码如下:

<?php
namespace app\Service;
use app\Models\Study\StudentModel;
use think\Exception;

class StudentService
{
  public function update($id = 1){
      try {
          $student =  StudentModel::where('id',$id)->find();
          //这里修改主键 id 的值,并保存会报错
          $student->id = "test";
          $student->save();
      }catch(\Exception $e){
            throw new Exception("数据保存失败:".$e->getMessage());
      }
  }
}

Tips: 上述代码是为了演示方便故意写的一个报错代码,目的是为了异常捕获。

4. 请求接口

postman 中请求接口,返回数据如下:
图片描述

Tips: 如图所示可以使用异常捕获之后,可以防止由于代码逻辑错误导致的内部 500,从而返回友好的 200,上述展示的是多层异常捕获。

5. 主动抛出异常

上述 StudentService 类中 update 方法也可以定义如下方式主动抛出异常:

  public function update($id = 0){
        if(!$id){
            throw new Exception("id必须大于0");
        }

        $student = StudentModel::where('id',$id)->find();
        if(empty($student)){
            throw new Exception("学生信息不存在");
        }
  }

如下图所示:
图片描述

此时再调用接口返回如下图:
图片描述

6. 小结

本小节介绍了如何使用异常捕获,异常捕获可以有效地捕捉多层调用关系的内部异常,当内部代码出现报错情况时,在控制器入口处捕获异常可以有效地阻止 500 错误码,然后返回更加友好的 200 状态码。

Tips: 代码仓库:https://gitee.com/love-for-poetry/tp6