最常用方式是手动拼json并调用$response->end(),需设content-type、用json_unescaped_unicode等标志,避免不可序列化数据导致空响应,禁用echo/print,状态码须在end()前调用status()。

直接用 $response->end() 返回 JSON 字符串
最常用、最轻量的方式就是手动拼 JSON 字符串,然后调用 $response->end() 发送。Swoole HTTP 服务本身不自动序列化,也不强制要求 Content-Type,必须自己设。
常见错误是只写 $response->end(json_encode($data)) 却忘了设响应头,导致前端解析失败或触发 CORS 预检失败。
- 务必手动设置
Content-Type: application/json; charset=utf-8 -
json_encode()要加JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES,避免中文转义和多余反斜杠 - 如果
$data含资源(如 MySQL result)、闭包或不可序列化对象,json_encode()会静默返回false,需提前检查
$response->header('Content-Type', 'application/json; charset=utf-8');
$response->end(json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
为什么不能用 echo 或 print
Swoole HTTP Server 是异步非阻塞的,所有响应必须通过 $response 对象控制,echo 和 print 输出到 CLI 标准输出,对客户端完全无效,还会干扰日志或引发 warning(尤其在协程环境下)。
容易踩的坑:
- 在
onRequest回调里混用echo和$response->end()—— 前者无效果,后者可能被忽略(因响应已发送) - 误以为类似 PHP-FPM 的“脚本结束即响应”,但 Swoole 必须显式调用
end()、write()或status()等方法才真正发出响应
需要状态码或分块响应时用 $response->status() + $response->end()
比如返回 404、500 或自定义状态码,不能只靠 JSON 内容,必须调用 status() 显式设置 HTTP 状态码。它必须在 end() 之前调用,且只生效一次。
详细的 Three.js 3D 图形参考,涵盖场景设置、相机、几何体、材质、光照、动画、控制器、加载器、数学工具和调试。
注意点:
-
$response->status(404)不会自动终止响应,后续仍需end()输出内容 - 若先
end()再status(),状态码会被忽略(响应头已发出) - 要流式返回大 JSON(如导出),可用
write()分段发送,但需自行处理 JSON 结构完整性(比如不要把一个对象切开)
$response->status(400);
$response->header('Content-Type', 'application/json; charset=utf-8');
$response->end(json_encode(['error' => 'Invalid request'], JSON_UNESCAPED_UNICODE));
用 json_encode() 前务必过滤不可序列化字段
数据库模型、PDOStatement、resource、Closure、未公开属性等都会让 json_encode() 返回 false,而 Swoole 不报错,只会发空响应,前端看到的是空白或解析错误。
推荐做法:
- 用
is_array()或is_object()判断后,再用array_map()或对象转数组(如(array)$obj)预处理 - 对 Laravel/Eloquent 模型,优先用
toArray()或jsonSerialize()方法 - 简单兜底:加判断
if ($json === false) { $response->status(500)->end('{"error":"json encode failed"}'); }
复杂结构建议封装成小函数,统一处理 null、NaN、资源、循环引用等边界情况。










