ThinkPHP 异常接管自定义各模块返回结构

使用Spring Boot进行接口开发的小伙伴为了便于前端处理,都会封装一个统一异常处理的操作,只需要使用 @ControllerAdvice以及 @ExceptionHandler这两个注解即可,前者是用来开启全局的异常捕获,后者则是说明捕获哪些异常,对那些异常进行处理。
示例代码如下:

@ControllerAdvice
public class MyExceptionHandler {

    @ExceptionHandler(value =Exception.class)
	public String exceptionHandler(Exception e){
		System.out.println("发生了一个异常"+e);
       	return e.getMessage();
    }
}

接下来看一下ThinkPHP版本的
官方文档链接:https://doc.thinkphp.cn/v5_1/yichangchuli.html#%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86%E6%8E%A5%E7%AE%A1
方法很简单,只需要自定义一个类,然后继承think\exception\Handle并且实现render方法。
示例代码如下:

<?php
namespace app\common\exception;

use Exception;
use think\exception\Handle;
use think\exception\HttpException;
use think\exception\ValidateException;

class Http extends Handle
{
    public function render(Exception $e)
    {
        // 参数验证错误
        if ($e instanceof ValidateException) {
            return json($e->getError(), 422);
        }

        // 请求异常
        if ($e instanceof HttpException && request()->isAjax()) {
            return response($e->getMessage(), $e->getStatusCode());
        }

        // 其他错误交给系统处理
        return parent::render($e);
    }

}

要启用该功能,还需要配置下异常处理handle类。

在项目config目录下的app.php完成如下配置即可

'exception_handle' => '\\app\\common\\exception\\Http',

上面创建的类文件需要跟配置的一致
类目录:application/common/exception
类文件名:Http.php
具体路径跟文件名均可自定义,只需要跟配置保持一致即可,当然还是建议跟官方保持一致,方便新人理解

会发现上面的配置是一个公共的配置,当我们使用多模块模式进行开发且各模块返回结构有差异的时候(如api模块需要返回json,index模块需要返回页面),就有点难办了。
第一种解决方案,是在上面的Http.php类中通过request()->module()获取模块名称,然后再自行追加判断
第二种解决方案,在config目录下创建模块对应的目录,如:index、api,然后在目录下新建一个app.php文件,在其中写入exception_handle即可,示例代码如下:

<?php
//配置文件
return [
    // 异常处理handle类 留空使用 \think\exception\Handle
    'exception_handle' => '\\app\\api\\exception\\Http',
];

方案一会充斥着各种判断,不利于阅读
方案二完美解决了上面的问题且修改当前模块的业务逻辑不会对其他模块造成影响

Tagged , ,