swoole 的 document_root 不接受相对路径是底层硬性限制,因其直接调用 stat() 等系统调用,不解析当前工作目录,传入 "./static" 等路径会按启动时实际工作目录查找,极易导致静态文件 404 且无报错。

document_root 不接受相对路径是 Swoole 底层硬性限制
Swoole 的 document_root 参数在底层调用 stat() 或 openat() 等系统调用时,直接传入字符串路径。它不经过 PHP 的当前工作目录(getcwd())解析,也不做任何路径补全。一旦你传入 "./static" 或 "../public/static",Swoole 就会尝试在进程启动时的**实际工作目录**(通常是 shell 当前目录,而非项目根目录)下找这个路径——绝大多数情况下根本不存在,导致静态文件 404,且不会报错,只默默 fallback 到 PHP 路由。
CLI 启动场景下相对路径完全不可控
Supervisor、systemd、crontab 或 Docker 容器中启动 Swoole 服务时,进程的工作目录极可能不是你预期的项目根目录:
-
supervisord默认以/或用户 home 目录为工作目录,./public/static会指向/public/static,显然错误 - Docker 中若未显式
WORKDIR,工作目录是镜像默认值(如/),../public会越界到根目录上层(无效) - PHP CLI 模式下
__DIR__是当前脚本所在目录,但document_root是独立配置项,不继承该上下文
ThinkPHP + think-swoole 扩展里 document_root 的典型陷阱
很多人照着文档写 'document_root' => __DIR__ . '/../public/static',看起来是绝对路径拼接,但这里有个隐蔽坑点:
-
__DIR__在config/swoole.php中执行时,指向的是config/目录,不是入口脚本或框架核心目录 - 如果项目结构变动(比如把
config/移到app/config/),__DIR__结果就变了,路径立刻失效 - 更稳妥的做法是用
dirname(dirname(__DIR__)) . '/public/static',或直接写死绝对路径(如/var/www/myapp/public/static) - Windows 下注意斜杠方向:
__DIR__ . '\..\public\static'可能被某些版本 Swoole 拒绝,统一用正斜杠/更安全
为什么 Swoole 不自己 resolve 相对路径?
这不是疏忽,而是设计取舍:
- 避免隐式依赖
getcwd()—— 该函数在多线程/协程环境下行为不稳定,Swoole 追求确定性 - 减少运行时开销:每次 HTTP 请求都要判断并拼接路径,对高频静态请求是性能负担
- 强制使用者明确资源位置,防止部署时因工作目录差异导致环境不一致(Dev 正常、Prod 404)
所以别指望它“聪明”,给什么路径,它就查什么路径。写错一个字符,静态资源就消失,而且日志里通常不报错——这是最要命的地方。











