ThinkPHP的异常处理设计

就算人生终有一散,也别辜负相遇

异常的分类

  • 用户行为异常
    提交了错误的参数
    没有查询到结果
    通常不需要记录日志, 需要给用户返回具体的错误信息, 而且一般情况下这些异常是可以预见的;

  • 系统异常
    代码自己的错误
    需要记录日志, 不应该向客户返回具体的信息,一般无法预见

自定义异常捕捉类

修改配置文件tp5\application\config.php

1
'exception_handle'       => 'app\lib\exception\ExceptionHandler'

tp5\application\lib\exception\ExceptionHandler.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<?php
namespace app\lib\exception;

use think\exception\Handle;
use think\Log;
use think\Request;

class ExceptionHandler extends Handle
{
public $code;

public $msg;

public $errorCode;

public function render(\Exception $e)
{
if ($e instanceof BaseException) {
// 自定义异常
$this->code = $e->code;
$this->msg = $e->msg;
$this->errorCode = $e->errorCode;
} else {
// 调试环境使用tp自己的异常类, 便于调试
if (config('app_debug')) {
return parent::render($e);
}
$this->code = 500;
$this->msg = '服务器内部错误';
$this->errorCode = 999;
// 异常
$this->recordErrorLog($e);
}

$request = Request::instance();

$res = [
'msg' => $this->msg,
'error_code' => $this->errorCode,
'request_url' => $request->url()
];

// 以 json 的结构返回异常
return json($res, $this->code);

}

/*
* 将异常写入日志
*/
private function recordErrorLog(\Exception $e)
{
Log::init([
'type' => 'File',
'path' => LOG_PATH,
'level' => ['error']
]);

Log::record($e->getMessage(),'error');
}
}

控制器

在结果为空的时候抛出一个自定义的异常
tp5\application\api\controller\v1\Products.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
use app\lib\exception\ProductException;

public function getRecent($count = 15)
{
(new Count())->goCheck();

$res = Product::getMostRecent($count);

if ($res->isEmpty()) {
throw new ProductException();
}

$res = $res->hidden(['summary']);

return $res;
}

异常基类

tp5\application\lib\exception\BaseException.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php

namespace app\lib\exception;

use think\Exception;

class BaseException extends Exception
{
public $code = 500;

public $msg = '请求错误';

public $errorCode = 10000;

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->msg = $params['msg'];
}
if(array_key_exists('errorCode',$params)) {
$this->errorCode = $params['errorCode'];
}
}
}

自定义异常类

覆盖基类的几个基本参数, 实现不同的异常返回不同的参数

1
2
3
4
5
6
7
8
9
10
<?php

namespace app\lib\exception;

class ProductException extends BaseException
{
public $code = 404;
public $msg = '指定商品不存在,请检查商品ID';
public $errorCode = 20000;
}