mtphp 文档

统一异常处理、健康检查与请求链路

这三块让 mtphp 在真实 API 后端 / k8s 场景里"开箱即可用",全部零依赖。

30.1 统一异常渲染(业务异常自动转 JSON 信封)

应用层抛出的异常,由 Mtphp\App::toErrorResponse 统一收口,按"请求是否期望 JSON"决定渲染格式:

三类异常的处理:

异常HTTP 状态码信封 codedata
Mtphp\Exception\ApiException($msg, $businessCode, $httpStatus, $data)$httpStatus$businessCode(业务码,前端分支用)$data
Mtphp\Validation\ValidationException($request->validate() 抛出)422422{errors: 字段=>消息}
其它 HttpException / Throwable其状态码 / 500= HTTP 状态码(404→Not Found,500→Internal Server Error)调试期含 file/trace

ApiException 是你在 service / controller 里直接抛的"业务异常",业务码与 HTTP 状态码解耦(前端按 code 分支、网关按 HTTP 状态路由)。

use Mtphp\Exception\ApiException;
throw new ApiException('余额不足', 4001, 400, ['need' => 100]);
// → {"code":4001,"message":"余额不足","data":{"need":100},"request_id":"...", HTTP 400

30.2 健康检查 / 探针端点

Mtphp\Http\Middleware\HealthCheck 默认自动注册(可在 config/app.php 关闭:'health_probe' => false),在洋葱最外层短路拦截,不进入路由/控制器:

注册自定义检查(如 Redis):

use Mtphp\Http\Middleware\HealthCheck;
HealthCheck::check('redis', function (): array {
    try { /* ping */ return ['ok' => true]; }
    catch (\Throwable $e) { return ['ok' => false, 'error' => $e->getMessage()]; }
});

当 config/database.default 已配置时,框架会自动把"数据库连接可达性"作为 /ready 的一项 db 检查。

30.3 请求 ID 与链路追踪

每个请求都会获得一个 ID:优先复用入站 X-Request-Id 头(便于贯通上游链路),否则自动生成。它在三处自动贯通:

Mtphp\Http\Request::requestId() / setRequestId()。

30.4 结构化日志(JSON 行)

既有的 Mtphp\Log\Logger(PSR-3 八级、single/daily 驱动)新增 JSON 行模式:按通道在 config/log.php 设 'format' => 'json' 即可开启,默认仍是人读文本(向后兼容)。

JSON 行形如:

{"ts":"2026-10-21T19:00:00+08:00","level":"ERROR","msg":"出错了","request_id":"...","context":{"order_id":9}}

request_id 由框架在请求入口经 Logger::setRequestId() 注入,日志自动带上;CLI 场景为 null。非常适合 ELK / Loki 等日志采集。

// config/log.php:'single' => ['driver'=>'single','path'=>'runtime/logs/app.log','level'=>'info','format'=>'json']
logger()->error('支付回调失败', ['order_id' => 9]);   // 该行携带 request_id

配套零依赖单测 tests/ExceptionHandlingTest.php(14 用例 / 42 断言):覆盖 ApiException 字段、/healthz 与 /ready 通过/失败、请求 ID 取自头与自动生成、JSON 结构化日志含 request_id、以及 App 对 ApiException/Validation/404(JSON)/HTML 的错误信封渲染。php tests/run.php ExceptionHandlingTest 单独跑;全量 php tests/run.php 也已通过。