Nginx子目录部署必须配合伪静态,否则ThinkPHP/Laravel等框架会路由失灵、404或白屏;需单独声明location /myapp/块,用try_files替代if+rewrite,并同步调整框架的url_html_suffix、pathinfo_depr等配置。

Nginx 虚拟目录(即子目录部署)和伪静态必须配合使用,否则 ThinkPHP、Laravel 等框架在二级路径下会路由失灵、404 或白屏。关键不是“能不能一起用”,而是必须用对结构、写对位置、配对参数。
虚拟目录必须单独声明 location 块
不能把子目录规则塞进根 location / 里。比如项目访问地址是 https://example.com/myapp/,入口文件在 D:/www/myapp/public/index.php,那就要显式写:
location /myapp/ {
if (!-e $request_filename) {
rewrite ^/myapp/(.*)$ /myapp/index.php?s=$1 last;
}
}
注意三点:
-
/myapp/末尾斜杠不能丢,否则/myapp(无斜杠)请求不匹配 -
root指令必须写在server级,指向站点根目录(如D:/www),不是myapp子目录 -
index.php必须真实存在,且路径与 rewrite 中的/myapp/index.php一致
更稳的写法:用 try_files 替代 if + rewrite
Windows 下 if 在高并发或 PHP 8.0+ 环境中易清空 PATH_INFO,导致 ThinkPHP 白屏。推荐改用:
location /myapp/ {
alias D:/www/myapp/public/;
try_files $uri $uri/ /myapp/public/index.php?$query_string;
}
同时确保:
-
alias后路径末尾带/,且与try_files中的 fallback 路径层级对齐 - PHP 处理块含
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;(不能用$document_root) - 若用 ThinkPHP 6/8,
root应指向public目录,或直接用alias明确物理路径
ThinkPHP 子目录专项配置项
光配 Nginx 不够,框架层也得同步调整:
- 关闭
url_html_suffix(设为空字符串),否则/myapp/user会被强加.html后缀,404 - 设置
pathinfo_depr为'/',与 Nginx rewrite 中s=/user/list的分隔符一致 - 确保
url_route_on = true,否则整个路由系统不生效 -
APP_ENV设为production或debug,避免因环境误判跳过路由
避免常见踩坑点
- ❌ 把
rewrite ^/myapp/(.*)$ ...写在location /里面 → 规则不触发,s= 参数为空 - ❌
root写在location /myapp/块内 → 覆盖全局 root,导致 PHP 找不到 autoload - ❌ 入口文件在
public/,但 rewrite 指向/myapp/index.php(漏了public)→ 500 错误 - ❌ 用
$document_root代替$realpath_root→ 符号链接失效,ThinkPHP 8 加载失败
不复杂但容易忽略。











