tp5.1中需统一api响应结构为{"code":0,"msg":"success","data":{}},通过自定义json响应类、全局中间件兜底及basecontroller封装三步实现,兼顾主动return json()、验证失败、异常抛出及模型序列化兼容性。

TP5.1 项目中需让所有 API 接口返回统一的 {"code":0,"msg":"success","data":{}} 结构,避免控制器里反复手写数组、混用 $this->success() 和 return json() 导致前端解析错乱,同时要兼容验证失败、异常抛出等非主动调用路径。
替换 Json 响应类,接管主动 return json() 调用
第一步:在 app\common\response\Json.php 创建新类,命名空间为 app\common\response,继承 think\response\Json。
第二步:只重写 protected function output($data): string 方法,构造标准结构:['code' => $this->code, 'msg' => $this->message, 'data' => $data],再用 json_encode(..., JSON_UNESCAPED_UNICODE) 返回字符串。
第三步:在 app\common\provider\AppServiceProvider.php 的 register() 方法中绑定容器:$this->app->bind('think\response\Json', \app\common\response\Json::class);。【不覆盖 vendor 文件,否则 composer update 会丢失】
这一步只影响你写的 return json($data),不影响状态码和消息字段——因为 $this->code 和 $this->message 是框架根据 json($data, 400, [], ['code'=>1]) 第四个参数自动设的,乱改 __construct 会导致 return json($data, 400) 失效。
用中间件兜底所有非主动响应路径
方法一:新建中间件 app\middleware\UniformJsonResponse.php,handle() 中判断 $response instanceof \think\Response 且 !$response instanceof \think\response\Json。
方法二:提取原始响应内容——若 $response->getContent() 是 JSON 字符串,用 json_decode($content, true) 解析;若已是数组(如验证异常默认输出),直接取用;否则统一包装为 ['code'=>500,'msg'=>'server error','data'=>null]。
方法三:用 response()->json($wrapped)->header(['Content-Type'=>'application/json; charset=utf-8']) 替换原响应对象,并确保该中间件注册为全局中间件,且执行顺序在 ResponseTrace 之后、输出之前。
注意:TP5.1 没有 JsonResponse 类型判断,必须靠 getContent() + json_last_error() 双重校验,否则 HTML 响应会被错误转成 JSON。
封装 BaseController 统一业务层输出方法
第一步:新建 app\common\controller\BaseController.php,继承 \think\Controller。
第二步:添加 protected function success($data = [], $msg = 'success', $code = 0) 方法,内部调用 return json(['code' => $code, 'msg' => $msg, 'data' => $data]);。
第三步:添加 protected function error($msg = 'error', $code = -1, $data = null),同样走 return json(...)。
所有 API 控制器改为继承此 BaseController,后续直接写 return $this->success($user) 即可。这比裸写 json() 更安全——【TP5.1 中 $this->json() 会报 Call to undefined method 错误,必须用 return json()】。
处理模型序列化失败的兼容逻辑
在 BaseController::success() 方法内,对 $data 执行预检:if (is_object($data) && !method_exists($data, '__toString')) { $data = []; }。
这能防止模型里含闭包、资源句柄或未实现 __toString() 的自定义对象时,触发 Fatal error: Object of class ... could not be converted to string。
如果项目用了 Eloquent 或自定义模型,建议额外加一层 try { json_encode($data); } catch (\Exception $e) { $data = []; },但不要记录日志——TP5.1 的日志通道可能尚未初始化。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











