大部分情况我们写程序返回给后端都是直接在需要返回的节点写个return即可,不管是前端请求需要的结果还是意料之外的结果都是如此,有时候我们可以使用抛出异常的方式告知前端获取的结果与其意愿不符。
大部分框架也都是有全局异常处理机制,下面就以ThinkPHP5来实践。
1新建自定义异常基类
namespace app\lib\exception;
use think\Exception;
/**
* Class BaseException
* 自定义异常类的基类
*/
class BaseException extends Exception
{
public $code = 400;
public $message = 'invalid parameters';
public $errorCode = 999;
public $shouldToClient = true;
/**
* 构造函数,接收一个关联数组
* @param array $params 关联数组只应包含code、msg和errorCode,且不应该是空值
*/
public function __construct($params=[])
{
if(!is_array($params)){
return;
}
if(array_key_exists('code',$params)){
$this->code = $params['code'];
}
if(array_key_exists('msg',$params)){
$this->message = $params['msg'];
}
if(array_key_exists('errorCode',$params)){
$this->errorCode = $params['errorCode'];
}
}
}
2新建异常处理类
namespace app\lib\exception;
use think\exception\Handle;
use think\Log;
use think\Request;
use Exception;
/*
* 重写Handle的render方法,实现自定义异常消息
*/
class ExceptionHandler extends Handle
{
private $code;
private $msg;
private $errorCode;
public function render(Exception $e)
{
if ($e instanceof BaseException)
{
//如果是自定义异常,则控制http状态码,不需要记录日志
//因为这些通常是因为客户端传递参数错误或者是用户请求造成的异常
//不应当记录日志
$this->code = $e->getCode();
$this->msg = $e->getMessage();
$this->errorCode = $e->errorCode;
} else{
// 如果是服务器未处理的异常,将http状态码设置为500,并记录日志
if(config('app_debug')){
// 调试状态下需要显示TP默认的异常页面,因为TP的默认页面
// 很容易看出问题
return parent::render($e);
}
$this->code = 500;
$this->msg = $e->getMessage();
$this->errorCode = 999;
$this->recordErrorLog($e);
}
$request = Request::instance();
$result = [
'msg' => $this->msg,
'error_code' => $this->errorCode,
'request_url' => $request = $request->url()
];
return json($result, $this->code);
}
/*
* 将异常写入日志
*/
private function recordErrorLog(Exception $e)
{
Log::init([
'type' => 'File',
'path' => LOG_PATH,
'level' => ['error']
]);
// Log::record($e->getTraceAsString(),'error');
Log::record($e->getMessage(),'error');
}
}
3 使用自定义异常处理接替框架异常处理
在tp框架./application/config.php中修改exception_handle为自定义异常处理类
'exception_handle' => 'app\lib\exception\ExceptionHandler',
4 使用
- 定义一个登陆异常类
namespace app\lib\exception;
class LoginException extends BaseException
{
public $code = 401;
public $message = '登录失败';
public $errorCode = 10003;
}
- 程序中使用
public static function loginByName($username,$password) {
$user = UserModel::getByName($username);
if (!$user){
throw new LoginException(['msg' => '用户不存在', 'errorCode' => 10005]);
}elseif(!self::checkPassword($user,$password)) {
throw new LoginException(['msg'=>'用户密码错误','errorCode'=>10002]);
} else {
return $user->toArray();
}
}