不能直接echo json_encode(),因为Hyperf是Swoole常驻内存框架,echo会绕过响应生命周期管理,导致Content-Type错误、状态码无法动态设置、中间件失效、CLI下报错;正确做法是依赖注入ResponseInterface并调用json()方法。

ResponseInterface 的 json() 方法是 Hyperf 控制器返回 JSON 的标准方式,无需手动 json_encode() 或设置 Header。
为什么不能直接 echo json_encode()?
Hyperf 是基于 Swoole 的常驻内存框架,直接 echo 会绕过响应生命周期管理,导致:
- Content-Type 不是
application/json(默认是text/html) - HTTP 状态码固定为 200,无法动态设为 400/500 等
- 后续中间件(如 CORS、日志记录)可能收不到完整响应对象
- 在 CLI 模式下(如测试、定时任务)可能直接报错或静默失败
正确用法:注入 ResponseInterface 并调用 json()
必须通过依赖注入获取 ResponseInterface 实例,不能 new 或静态调用。示例如下:
use Hyperf\HttpServer\Contract\ResponseInterface;
use Psr\Http\Message\ResponseInterface as Psr7ResponseInterface;
public function index(ResponseInterface $response): Psr7ResponseInterface
{
$data = ['code' => 200, 'msg' => 'ok', 'data' => ['id' => 1]];
return $response->json($data);
}
-
$response->json()自动设置Content-Type: application/json; charset=utf-8 - 支持传入第二个参数指定状态码:
$response->json($data, 201) - 第三个参数可传入 JSON 标志位,如
JSON_UNESCAPED_UNICODE - 返回值类型必须声明为
Psr7ResponseInterface,否则 Swoole 可能无法识别响应体
常见错误:raw() + 手动 json_encode() 代替 json()
有人写成这样:
return $response->raw(json_encode($data)); // ❌ 错误
问题在于:
-
raw()不自动设Content-Type,前端可能解析失败 - 中文字符若未加
JSON_UNESCAPED_UNICODE会被转义成 \uXXXX - 空数组
[]和关联数组[]在 PHP 中表现一致,但json()内部做了类型推导,raw()没有 - 异常时无法统一拦截 JSON 渲染逻辑(比如全局加
trace_id)
真正需要定制 JSON 行为(如统一加字段、改状态结构)应该在中间件或自定义 ResponseInterface 实现里处理,而不是在每个控制器里退化成 raw()。


















