swoft 学习笔记之异常处理
异常处理包含定义异常类和与之对应的异常处理类,处理类通常包含名字为 handle 的方法
一、定义异常类
<?php
namespace App\Exception;
Class ApiException extends \Exception {
}
二、定义异常处理类
<?php
namespace App\Exception\Handler;
use App\Exception\ApiException;
use Swoft\Error\Annotation\Mapping\ExceptionHandler;
use Swoft\Http\Message\Response;
use Swoft\Http\Server\Exception\Handler\AbstractHttpErrorHandler;
/**
* @ExceptionHandler(ApiException::class)
*/
class ApiExceptionHandler extends AbstractHttpErrorHandler
{
/**
* @param \Throwable $e
* @param Response $response
* @return Response
* @throws \ReflectionException
* @throws \Swoft\Bean\Exception\ContainerException
*/
public function handle(\Throwable $e, Response $response): Response
{
$data = [
'code' => -1,
'msg' => $e->getMessage()
];
return $response->withData($data);
}
}
三、HTTP异常接管
当在做 API 开发的时候,后端第一个要做的就是验证参数的合法性。当参数不合法时,会返回给客户端具体错误信息,此时是通过抛出异常的方式。因此我在系统自带的异常处理类里面稍微做了些修改。具体修改思路是:如果抛出的异常时验证类的异常,则直接返回给客户端错误信息,如果不是的话,再判断当前环境是开发调试还是生产,如果是调试生产,则抛出具体错误信息,方便调试,如果是生产环境,则没必要把详细的错误信息返回给客户端,因为客户端根本不关心具体错在哪了,此时需要统一返回服务端内部错误就行,并视情况而定,到底是否需要记录日志。
<?php declare(strict_types=1);
namespace App\Exception\Handler;
use const APP_DEBUG;
use function get_class;
use ReflectionException;
use function sprintf;
use Swoft\Bean\Exception\ContainerException;
use Swoft\Error\Annotation\Mapping\ExceptionHandler;
use Swoft\Http\Message\Response;
use Swoft\Http\Server\Exception\Handler\AbstractHttpErrorHandler;
use Swoft\Log\Helper\CLog;
use Throwable;
use App\Model\Struct\DataStruct;
use App\Model\Struct\ConstantStruct;
use Swoft\Validator\Exception\ValidatorException;
/**
* Class HttpExceptionHandler
*
* @ExceptionHandler(\Throwable::class)
*/
class HttpExceptionHandler extends AbstractHttpErrorHandler
{
/**
* @param Throwable $e
* @param Response $response
*
* @return Response
* @throws ReflectionException
* @throws ContainerException
*/
public function handle(Throwable $e, Response $response): Response
{
// Log
CLog::error($e->getMessage());
//如果是验证类异常,则返回给客户端,不需要记录日志
if( $e instanceof ValidatorException ){
$data = [
'code' => ConstantStruct::VALIDATOR_ERROR,
'msg' => $e->getMessage(),
];
return $response->withData($data);
}
//如果是系统内部异常,则判断是否是环境测试还是生产
//如果是非 debug 模式,则统一抛出系统内部错误
if ( ! APP_DEBUG ) {
$data = [
'code' => ConstantStruct::CODE_ERROR,
'msg' => $e->getMessage(),
];
return $response->withData($data);
}
//如果是 debug 模式,就抛出具体错误信息,便于调试
$data = [
'code' => $e->getCode(),
'error' => sprintf('(%s) %s', get_class($e), $e->getMessage()),
'file' => sprintf('At %s line %d', $e->getFile(), $e->getLine()),
'trace' => $e->getTraceAsString(),
];
return $response->withData($data);
}
}
本作品采用《CC 协议》,转载必须注明作者和本文链接