子目录部署thinkphp6时,nginx rewrite规则应写为:location /myapp/ { if (!-e $request_filename) { rewrite ^/myapp/(.*)$ /myapp/index.php?s=$1 last; } },需确保入口路径正确、path_info透传且重载nginx生效。

ThinkPHP6 在子目录部署时 rewrite 规则怎么写
子目录部署(如 https://example.com/myapp/)下,Nginx 默认的根目录 location / 规则会失效,必须显式匹配前缀,并把路径剥离后正确传给 index.php。否则 ThinkPHP6 无法解析 PATH_INFO 或 QUERY_STRING,直接 404。
关键点在于:既要让 Nginx 找到 index.php,又要让框架收到原始请求路径(比如 /myapp/user/list 中的 /user/list 部分)。
- 用
location ^~ /myapp/精确前缀匹配,避免正则干扰优先级 -
try_files $uri $uri/ /myapp/index.php?$query_string;—— 第三项必须带完整路径/myapp/index.php,不能省略 - 在
location ~ \.php$块里,fastcgi_param SCRIPT_FILENAME必须用$document_root$fastcgi_script_name,不能用$request_filename(重写后它可能指向错误物理路径) - 如果入口文件不在子目录根(比如你把
public/放在/myapp/public/),则root要设为上一级(如/var/www/html),再通过alias指向 public 目录,此时SCRIPT_FILENAME得改写为$document_root/myapp/public$fastcgi_script_name
Apache 下虚拟目录的 .htaccess 为什么不起作用
Windows + Apache 2.4 默认禁用 .htaccess 解析,即使你写了规则,Apache 也当它不存在。这不是 ThinkPHP 的问题,是 Apache 配置层级没放开。
必须在 httpd.conf 或对应 <virtualhost></virtualhost> 块中,对虚拟目录路径显式启用 AllowOverride:
- 确认该目录的
<directory></directory>块存在,且路径与 DocumentRoot 下实际路径一致(注意斜杠方向,Windows 推荐用正斜杠/) - 设置
AllowOverride All(或至少AllowOverride FileInfo Options=Indexes,FollowSymLinks) - 确保
LoadModule rewrite_module modules/mod_rewrite.so已启用(取消注释) - 重启 Apache 后,
.htaccess里的RewriteRule ^(.*)$ index.php [QSA,PT,L]才会生效
PHP8.1 + FastCGI 模式下 PATH_INFO 为空怎么办
Apache 的 mod_fcgid 不像 mod_php 那样自动填充 $_SERVER['PATH_INFO'],而 ThinkPHP6 默认依赖它做路由解析。不补全会导致所有非 index.php 开头的 URL 全部 404。
最稳妥的修复方式是在 public/index.php 顶部加一段环境兜底逻辑:
if (!isset($_SERVER['PATH_INFO']) && isset($_SERVER['REQUEST_URI'])) {
$_SERVER['PATH_INFO'] = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
}
- 这段代码必须放在
define('APP_PATH', ...)和require __DIR__ . '/../vendor/autoload.php';之前 - 不要用
$_SERVER['ORIG_PATH_INFO']—— 在 FastCGI 下它往往为空或不可靠 - 如果你改用 QUERY_STRING 模式(如
index.php?s=/user/list),需在config/app.php中设置'url_common' => false并启用'url_route_must' => true,但这样要同步改 Nginx/Apache 的 rewrite 规则,复杂度更高
为什么 /index.php/user/list 能访问,但 /user/list 就 404
这说明框架本身能跑,只是 Web 服务器没把请求转进来——99% 是 rewrite 规则没命中或转发路径错位。
排查顺序建议按这个走:
- 用
curl -I http://localhost/user/list看返回状态码和Location头,确认是否被重定向或直接 404 - 检查 Nginx error log(
/var/log/nginx/error.log)或 Apache error log(logs/error.log),搜索 “rewrite”、“no such file”、“script not found” - 临时在
index.php开头加file_put_contents('/tmp/debug.log', print_r($_SERVER, 1), FILE_APPEND);,看请求进来时REQUEST_URI、SCRIPT_NAME、PATH_INFO是否符合预期 - 确认
public/是唯一 Web 可访问目录,其他如app/、runtime/必须禁止外部访问(Apache 用<directory> Deny from all</directory>,Nginx 用location ~ ^/(app|config|runtime|vendor|\.git)/ { return 404; })
子目录部署时最容易漏掉的是 SCRIPT_FILENAME 路径拼接错误,或者 try_files 没把请求真正落到 index.php 上——这两处一旦出错,框架连启动机会都没有。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











