异常与错误处理
控制器内抛出的异常会进入 onException()。建议把参数错误、业务错误和系统错误转换成一致的响应格式。
定义业务异常
<?php
namespace App\Exception;
use RuntimeException;
class BusinessException extends RuntimeException
{
public function __construct(
string $message,
public readonly int $httpStatus = 400,
public readonly string $errorCode = 'BUSINESS_ERROR'
) {
parent::__construct($message);
}
}
控制器统一处理
use App\Exception\BusinessException;
use EasySwoole\EasySwoole\Trigger;
protected function onException(\Throwable $throwable): void
{
if ($throwable instanceof BusinessException) {
$this->writeJson(
$throwable->httpStatus,
['errorCode' => $throwable->errorCode],
$throwable->getMessage()
);
return;
}
Trigger::getInstance()->throwable($throwable);
$this->writeJson(500, null, '服务器内部错误');
}
不要把堆栈、数据库信息或磁盘路径直接返回给生产客户端。
404 Action
protected function actionNotFound(?string $action)
{
$this->writeJson(404, null, "Action {$action} not found");
}
Router 没有命中与控制器 Action 不存在是两个阶段。全局路由模式下,还可以通过 setRouterNotFoundCallBack() 设置路由级 404。
全局 HTTP 异常
Dispatcher 支持 setHttpExceptionHandler()。它适合处理控制器构造前、路由回调或 Dispatcher 层异常;控制器的 onException() 负责控制器生命周期内部异常。
注解参数验证失败会产生专门的异常,其处理示例见注解参数验证。
状态码建议
| 场景 | 状态码 |
|---|---|
| 参数格式或 JSON 错误 | 400 |
| 未认证 | 401 |
| 无权限 | 403 |
| 资源或 Action 不存在 | 404 |
| HTTP 方法错误 | 405 |
| 业务校验不通过 | 422 |
| 未预期服务端异常 | 500 |
状态码与业务 errorCode 分开:HTTP 状态表达协议结果,业务码用于客户端精确处理。