hyperf: 抛出自定义异常
一,自定义异常类
Exception/BusinessException.php
我们用官方提供的这个现成的类:
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace App\Exception;
use App\Constants\ErrorCode;
use Hyperf\Server\Exception\ServerException;
use Throwable;
class BusinessException extends ServerException
{
public function __construct(int $code = 0, string $message = null, Throwable $previous = null)
{
if (is_null($message)) {
$message = ErrorCode::getMessage($code);
}
parent::__construct($message, $code, $previous);
}
}
这个是原始的代码,未做修改
二,抛出异常
Business/ImageBusiness.php
<?php
namespace App\Business;
use App\Exception\BusinessException;
class ImageBusiness
{
public function getImageDetail($id) {
echo "\n抛出异常之前:id:".$id."\n";
throw new BusinessException(501,"自定义异常信息");
echo "\n抛出异常之后\n";
return [];
}
}
三,异常处理
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace App\Exception\Handler;
use App\Exception\BusinessException;
use App\Log\ExceptionLog;
use Hyperf\Context\ApplicationContext;
use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\ExceptionHandler\ExceptionHandler;
use Hyperf\HttpMessage\Stream\SwooleStream;
use Hyperf\HttpServer\Contract\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Throwable;
class AppExceptionHandler extends ExceptionHandler
{
protected ExceptionLog $loggerFile;
public function __construct(protected StdoutLoggerInterface $logger)
//public function __construct(LoggerFactory $loggerFactory)
{
$this->loggerFile = new ExceptionLog();
}
public function handle(Throwable $throwable, ResponseInterface $response)
{
//判断是否自定义异常 ,如果是自定义异常 ,则不再写入到日志
//判断$throwable的类型
if ($throwable instanceof BusinessException) {
//当前是自定义异常时,调用异常的render方法返回
echo "捕捉到的是自定义异常BusinessException\n";
// 格式化输出, 去掉JSON_UNESCAPED_UNICODE
$data = json_encode([
'code' => $throwable->getCode(),
'message' => $throwable->getMessage(),
]);
// 阻止异常冒泡
$this->stopPropagation();
//返回json
return $response->withStatus(200)->withBody(new SwooleStream($data));
}
//得到请求
$request = ApplicationContext::getContainer()->get(RequestInterface::class);
//得到请求信息
$ip = $request->getServerParams()['remote_addr'];
$time = date("Y-m-d H:i:s"); //访问时间
$method = $request->getMethod();
$url = $request->fullUrl();
//$status = $response->getStatusCode(); //返回时的状态码
//$size = $response->getBody()->getSize(); //内容大小
$protocol = $request->getProtocolVersion();
$agent = $request->getHeader('user-agent');
$agentStr = implode(",",$agent);
$params = $request->all();
$paramStr = "";
foreach ($params as $k => $value) {
$one = $k."=".$value;
if ($paramStr == "") {
$paramStr = $one;
} else {
$paramStr .= "\n".$one;
}
}
$content = $ip." ".$time." ".$method." ".$url." ".$protocol." ".$agentStr;
$content .= "\nparams:".$paramStr;
$this->loggerFile->info($content);
//写日志到文件
$this->loggerFile->info(sprintf('%s[%s] in %s', $throwable->getMessage(), $throwable->getLine(), $throwable->getFile()));
$this->loggerFile->info($throwable->getTraceAsString());
//输出报错信息到控制台
$this->logger->error(sprintf('%s[%s] in %s', $throwable->getMessage(), $throwable->getLine(), $throwable->getFile()));
$this->logger->error($throwable->getTraceAsString());
//得到当前环境,如果是生产环境,不打印错误信息,只打印代码即可
$appEnv = config('app_env','');
//echo "appEnv:\n";
//var_dump($appEnv);
if ($appEnv == 'prod' || $appEnv == 'production') {
$message = "内部错误";
} else {
$message = $throwable->getMessage();
}
// 格式化输出,支掉了, JSON_UNESCAPED_UNICODE
$data = json_encode([
'code' => $throwable->getCode(),
'message' => $message,
]);
// 阻止异常冒泡
$this->stopPropagation();
//返回json
return $response->withStatus(200)->withBody(new SwooleStream($data));
}
public function isValid(Throwable $throwable): bool
{
return true;
}
}
浙公网安备 33010602011771号