自定义thinkphp5.1异常
本文通过建立自定义的Exception跟Handle,从而达到自定义错误返回的效果,及拦截系统运行过程中的随机异常。
整体设计思路请参见RESTFUL错误返回设计
新建异常处理目录
在 application->common 新建目录 exception。
定义Base Exception Class
在exception目录下,新建PHP类 BaseException.php
<?php
namespace app\common\exception;
use think\Exception;
class BaseException extends Exception
{
public $httpCode;
public $errorCode;
public $errorMessage;
public $errorDetail;
public function __construct($httpCode, $errorCode, $errorMessage, $errorDetail)
{
$this->httpCode = $httpCode;
$this->errorCode = $errorCode;
$this->errorMessage = $errorMessage;
$this->errorDetail = $errorDetail;
}
}
定义 Custom Exception Class 继承 BaseException
这里用UserException作为示例。为什么要取名UserException,是为了将不同的异常拆分到不同的类文件中,这样使用的时候比较方便,不会所有异常都塞在同个文件中。
在exception目录下,新建PHP类 UserException.php
<?php
namespace app\common\exception;
class UserExcepiton extends BaseException
{
/**
* UserExcepiton constructor.
* @param $httpCode
* @param $errorCode
* @param $errorMessage
* @param $errorDetail
*/
public function __construct($httpCode, $errorCode, $errorMessage, $errorDetail)
{
parent::__construct($httpCode, $errorCode, $errorMessage, $errorDetail);
}
// 微信授权登录失败
/**
* @param $wxErrcode
* @param $wxErrmsg
* @throws UserExcepiton
*/
public static function wexinAuthFail($wxErrcode, $wxErrmsg)
{
throw new UserExcepiton('400', 'User.01',
'微信授权失败。', '微信错误代码:' . $wxErrcode . '微信错误信息:' . $wxErrmsg);
}
/**
* @param $accessToken
* @throws UserExcepiton
*/
public static function notLogin($accessToken){
throw new UserExcepiton('400', 'User.02','用户未登录。',
'access_token:'.$accessToken);
}
}
这里定义了两个方法,下面我们会讲到怎么抛出这两个异常,并被处理成错误返回。
定义Handle类
这个是很关键,它通过继承thinkphp提供的Exception/Handle,从而在response前拦截到所有异常并做进一步的处理。
在exception目录下,新建PHP类 CustomHandle.php
<?php
namespace app\common\exception;
use Exception;
use think\exception\Handle;
class CustomHandle extends Handle
{
private $httpCode;
private $errorCode;
private $errorMessage;
private $errorDetail;
public function render(Exception $e)
{
if ($e instanceof BaseException) {
$this->errorCode = $e->errorCode;
$this->errorMessage = $e->errorMessage;
$this->httpCode = $e->httpCode;
$this->errorDetail = $e->errorDetail;
} else {
if (config('app_debug')) {
return parent::render($e);
}
$this->httpCode = 500;
$this->errorCode = "000000";
$this->errorMessage = "服务器未知错误";
$this->errorDetail = $e->getMessage();
}
$path = "http://" . request()->host() . ":" . request()->port() . request()->baseUrl();
$content = request()->getContent();
$queryString = request()->query();
$result = [
'path' => $path,
'error_code' => $this->errorCode,
'error_message' => $this->errorMessage,
'error_detail' => $this->errorDetail,
'query_string' => $queryString,
'content' => $content
];
return json($result, $this->httpCode);
}
}
说明:
1、这里通过 if ($e instanceof BaseException)
判断是否是我们自定义的异常,如果不是。那是系统抛出,说明我们遇到了未知错误(BUG)。
2、如果遇到了未知错误,还要继续 if (config('app_debug'))
判断当前是否处于调试模式,如果是就不处理,返回thinkphp的调试信息,如果不是就处理成统一的错误返回。
3、这部分程序还没有最终完成,按照设计要求,当遇到未知异常时,应该返回动态错误代码并记录系统日志,这里并没有,而是简单的返回000000。这样并不利于后期追溯问题。
最终的目录结构
抛出自定义异常
定义完上面这三个类后,我们就可以在程序中任意位置抛出这些异常,无论是db层,service层,还是controller层,都会得到响应,并且终止当前程序,向客户端返回错误信息。
下面示例是请求一个数据上传接口,在access token检验不通过时,返回用户未登录的错误信息。注意,这里的错误返回是service层check_login抛出的,而不是controller层。这也是采用异常处理机制最大的好处,就是你可以在任何地方终止掉程序。
-- Controller
/**
* @route('/drug-used-plan/upload')
*/
public
function upload()
{
$accessToken = explode(' ', $this->request->header('Authorization'))[1];
$loginStatus = $this->userService->check_login($accessToken);
$userId = $loginStatus->user_id;
$drug_plan = $this->request->post('drug_plan');
$this->drugUsedPlanService->uploadPlan($userId, $drug_plan);
return json(CustomResponse::commonResponse());
}
-- Service
public function check_login($accessToken)
{
$loginStatus = $this->getLoginStatusFromCache($accessToken);
if ($loginStatus) {
return $loginStatus;
} else {
// 抛出异常
throw UserExcepiton::notLogin($accessToken);
}
}
版权声明:如无特别声明,本文版权归 一年四季 所有,转载请注明本文链接。
(采用 CC BY-NC-SA 4.0 许可协议进行授权)
本文标题:《 自定义thinkphp5.1异常 》
本文链接:https://www.yucanlin.cn/develop/%E8%87%AA%E5%AE%9A%E4%B9%89thinkphp5%E5%BC%82%E5%B8%B8.html