if (!-e $request_filename) 必须置于 location / { } 块内且在 location ~ \.php$ 之前,用于判断静态文件不存在时重写为 /index.php?s=...;不可放 server 顶层、其他 location 内或 .php 块中,rewrite 必用 last 而非 break。

ThinkPHP 8.0 在 Nginx 1.20 中使用 if (!-e $request_filename) 规则时,必须放在 location / { } 块内,且严格位于 location ~ \.php$ 块之前。
这个位置不是可选的,而是由 Nginx 的匹配机制决定的:
-
location /是最宽泛的前缀匹配,作为兜底规则,负责处理所有请求; - 它需要先判断当前请求是否对应真实存在的静态文件或目录(如
.js、/favicon.ico); - 只有当
if (!-e $request_filename)判定“不存在”时,才通过rewrite把请求内部重写为/index.php?s=...,交由 PHP 处理; - 如果写在
location ~ \.php$里,该if根本不会执行——因为/user/list这类地址不以.php结尾,压根进不了这个块。
正确写法示例(精简关键部分):
server {
root /www/wwwroot/myapp/public;
location / {
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?s=$1 last;
}
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
include fastcgi_params;
}
}
注意三点:
- ✅
if必须嵌套在location /内,不能放在server顶层,也不能嵌套在其他location(如location /admin/)里; - ✅
rewrite中的s=$1是 ThinkPHP 默认的 PATH_INFO 入口参数名,不可改为s=/或省略; - ❌ 不要加
break(旧教程常见错误),它会中断后续的路径解析,导致子目录或二级路由失效;应使用last。
虽然 try_files 更推荐(更安全、无 if 副作用),但若你明确需用 if (!-e ...)(例如兼容某些小皮面板或遗留环境),那就只放这一个地方:location / 块开头,紧贴 { 后。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











