核心问题是查询参数丢失,需用try_files $uri $uri/ /index.php?$query_string;完整传递get参数;若用pathinfo模式,还需确保fastcgi_param path_info $fastcgi_path_info;、cgi.fix_pathinfo=1且禁用fastcgi_split_path_info。

ThinkPHP在Nginx伪静态配置后,带参数的路由(如 /user/profile/id/123 或 /index.php?s=user/profile&id=123)无法访问,核心问题通常不是路由本身写错了,而是请求转发过程中关键参数丢失或解析错位。重点不在“怎么写规则”,而在“参数是否完整抵达PHP”。
必须确保 ?query_string 被显式传递
很多 Nginx 配置只写 rewrite ^(.*)$ /index.php?s=$1 last;,这会丢弃原始 URL 中的 ?id=123 这类查询参数。$_GET 为空、$request->param('id') 拿不到值,就是这个原因。
正确做法是:在 try_files 或 rewrite 中保留 $query_string。
✅ 推荐用
try_files $uri $uri/ /index.php?$query_string;
它把整个查询字符串原样传给 index.php,ThinkPHP 5/6/8 均能识别s=参数和额外GET参数。❌ 避免
rewrite ^(.*)$ /index.php?s=$1 last;$1只捕获路径部分,不包含?后的内容;且在子目录或 PATH_INFO 模式下易出错。
检查 PHP-FPM 是否透传了 PATH_INFO(尤其 TP6/TP8)
如果使用的是 pathinfo 模式(如 /index.php/user/profile/id/123),而页面报 “URL pathinfo not supported”,说明 $_SERVER['PATH_INFO'] 是空或非法。
需确认以下三项都到位:
-
fastcgi_param PATH_INFO $fastcgi_path_info;在location ~ \.php$块中存在(不能被注释或删除) -
php.ini中cgi.fix_pathinfo = 1(默认为 1,但 Docker 或加固环境常被设为 0) - Nginx 的
fastcgi_split_path_info行应删除或注释——ThinkPHP 不需要它,留着反而干扰
子目录部署时路径前缀必须显式处理
比如站点访问地址是 https://example.com/myapp/,入口实际是 /myapp/public/index.php,那么:
-
root必须指向项目根目录(如/www/wwwroot/example.com),不是 public -
location /myapp/内要用带前缀的 rewrite:location /myapp/ { if (!-e $request_filename) { rewrite ^/myapp/(.*)$ /myapp/index.php?s=$1 last; } } - 更稳妥的方式是改用
try_files并修正 fallback 路径:location /myapp/ { try_files $uri $uri/ /myapp/index.php?$query_string; }
最后验证一步:直接访问带参数的 index.php
在浏览器中打开:https://your-domain.com/index.php?s=user/profile&id=123
- 若能正常响应 → 说明框架和 PHP 没问题,纯属伪静态转发缺陷
- 若仍 404 或空白 → 检查
url_route_on = true、APP_ENV是否为production(开发模式下部分路由可能被禁用)、runtime 目录权限是否允许写入
不复杂但容易忽略
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











