Closed ichynul closed 2 years ago
开发者可以实现自己的handler,决定BusinessException是否当作程序错误,并记录日志。 目前默认handler里没有把 BusinessException 当错程序错误,不记录日志。 如果强行规定死BusinessException的行为感觉不妥。
那改一下,render方法。默认返回null,需要自定义输出的就继承并重写此方法,不重写的话就跟以前的一样。
class BusinessException extends Exception
{
public function render(Request $request): ?Response
{
return null; //可返回Response或null
//$code = $this->getCode();
//if ($request->expectsJson()) {
// $json = ['code' => $code ? $code : 500, 'msg' => $this->getMessage()];
// return new Response(200, ['Content-Type' => 'application/json'],
// \json_encode($json, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
// }
//return new Response(200, [], $this->getMessage());
}
}
开发者既要自己定义Exception
,又要自定义ExceptionHandler
,看似灵活,其实很麻烦。
目前我是通过中间件根据$response->exception() instanceof
来判断并处理返回内容。唯一的不足__construct里面抛出的错误无法在中间件里面捕获。
业务错误,我觉得主要是方便在程序里面任何位置中断执行,在其他fpm框架框架,倒有很多替代方案,可以是exit,die之类的。
它有两个关键点:1、不需要记录日志,2、要给显示给用户提示。解决了这两个问题,真没必要去自定义。
或者controller_reuse的时候,实列化控制器也trycatch 一下。 不复用控制器的情况下,有些人可能通过继承控制器,在基类__construct里面进行一些检查,然后抛出业务异常。 这个异常仍然在经过中间件返回,就可以在里面捕获了。 https://github.com/walkor/webman-framework/blob/1860a6a4c670b5ac85a1b44d019466f2ea49742e/src/App.php#L260
$controller_reuse = static::config($plugin, 'app.controller_reuse', true);
if (\is_array($call) && \is_string($call[0])) {
if (!$controller_reuse) {
$call = function ($request, ...$args) use ($call, $plugin) {
try {
$call[0] = static::container($plugin)->make($call[0]);
return $call($request, ...$args);
} catch (Throwable $e) {
return static::exceptionResponse($e, $request);
}
};
} else {
$call[0] = static::container($plugin)->get($call[0]);
}
}
开发者既要自己定义Exception,又要自定义ExceptionHandler,看似灵活,其实很麻烦。
开发者什么都不需要做,目前BusinessException默认就是不算程序错误,也不会记录日志,只会给前端提示。
controller_reuse为false的时候,中间件是可以捕捉到__construct的异常的。但是controller_reuse为true的时候,因为控制器实例化时机问题,中间件没办法捕获__construct的异常。
1.在不自定义ExceptionHandler的情况下,BusinessException的渲染输出和其他程序错误都用的是同一个render方法。
$json = ['code' => $code ? $code : 500, 'msg' => $this->_debug ? $exception->getMessage() : 'Server internal error'];
在未开启debug模式时提示给用户的是 Server internal error
2.中间件是可以捕捉到__construct的异常的问题我再研究一下。
我懂你的意思了,pr还原成第一版吧,我合并下。
非常感谢。已经合并,等过几天发版本
OK
$json = ['code' => $code ? $code : 500, 'msg' => $this->getMessage()];
//这里可能需要再优化一下,有的会以 :0/1作为成功与否,0会被换成500。
控制器不重用后,控制器的
__construct()
方法里面的错误无法被中间件捕获到,不怎么方便。BusinessException
不属于程序错误,应该方便用户直接返回一个业务方面的提示信息。 用户也可在不自定义ExceptionHandler的情况下,以继承BusinessException实现其他业务方面的功能。 在程序的任何地方抛出错误,简单粗暴。