如何配置Nginx使ThinkPHP支持伪静态和多语言重写?
- 内容介绍
- 文章标签
- 相关推荐
本文共计961个文字,预计阅读时间需要4分钟。
ThinkPHP框架下,伪静态在Nginx配置中无法正常使用,90%以上不是框架问题,而是配置错误。常见问题包括没有正确设置`try_files`指令,缺少`SCRIPT_FILENAME`路径或路径错误,或没有正确设置请求落点到`index.php`。
为什么 ThinkPHP 路由返回 404?Nginx 根本没把请求交给它
默认 Nginx 配置会直接查找 /user/list 对应的物理文件,找不到就甩个 404 —— index.php 压根没被加载,更别说跑路由了。
- 必须用
try_files $uri $uri/ /index.php?$query_string;,确保所有非静态请求兜底到入口文件 - 别用
rewrite ^/(.*)$ /index.php/$1 last;:旧式写法容易循环重定向,且 PHP 无法从$_SERVER['PATH_INFO']正确提取路径 - 如果部署在子目录(如
https://example.com/app/),location必须带前缀,try_files中的/index.php得改成/app/index.php -
root必须指向public/目录,不是项目根目录;否则$document_root/index.php就是错的路径
多语言 URL 如何重写?ThinkPHP 不需要特殊 Nginx 规则
ThinkPHP 的多语言切换(比如 zh-CN、en-US)靠的是路由参数或中间件识别 Accept-Language、URL 前缀、Cookie 等,**Nginx 层不需要为语言加额外重写规则**。
- 若用 URL 前缀方式(如
/zh-CN/user/login),只要保证整个请求仍被try_files推给index.php,框架就能从$_SERVER['REQUEST_URI']解析出完整路径 - 别试图在 Nginx 里做语言跳转(比如
rewrite ^/zh-CN/(.*)$ /$1 break;),这会破坏路由上下文,导致url()生成错误链接 - 确保
fastcgi_param REQUEST_URI $request_uri;存在,否则框架看到的 URI 是重写前的,语言前缀会丢失
SCRIPT_FILENAME 报 “No input file specified” 怎么修?
这是最典型的 500 错误,本质是 PHP-FPM 收到了一个不存在或权限不对的文件路径。
立即学习“PHP免费学习笔记(深入)”;
- 检查
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;—— 这行必须存在,且不能写死成/var/www/app/public/index.php - 确认
root和$document_root一致:比如root /data/app/public;,那$document_root/index.php就得真实存在 - 运行
ls -l /data/app/public/index.php,确保 Nginx 用户(如www-data)有读权限 - 检查 PHP-FPM 的
security.limit_extensions是否包含.php(有些 Docker 镜像会删掉)
PATH_INFO 模式(url_model => 2)还值得配吗?
不推荐。ThinkPHP 6.x 默认走 QUERY_STRING 模式(?s=/user/list),更稳定、兼容性更好;PATH_INFO 在 Nginx 下需额外配置 fastcgi_split_path_info,稍有不慎就 404 或变量为空。
- 如果真要用 PATH_INFO,必须加这两行:
fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_param PATH_INFO $fastcgi_path_info;
- 但要注意:Nginx 的
if (!-e $request_filename)块和fastcgi_split_path_info不能混用,前者已被证明在某些版本下不可靠 - 更稳妥的做法是框架内保持
url_model => 0(兼容模式)或1(普通模式),Nginx 只管把请求交过去
真正卡住人的,往往不是要不要配多语言,而是 root 指向错了一级、try_files 少了个 ?、或者 SCRIPT_FILENAME 里漏了 $document_root —— 这些细节一错,整个路由链就断了。
本文共计961个文字,预计阅读时间需要4分钟。
ThinkPHP框架下,伪静态在Nginx配置中无法正常使用,90%以上不是框架问题,而是配置错误。常见问题包括没有正确设置`try_files`指令,缺少`SCRIPT_FILENAME`路径或路径错误,或没有正确设置请求落点到`index.php`。
为什么 ThinkPHP 路由返回 404?Nginx 根本没把请求交给它
默认 Nginx 配置会直接查找 /user/list 对应的物理文件,找不到就甩个 404 —— index.php 压根没被加载,更别说跑路由了。
- 必须用
try_files $uri $uri/ /index.php?$query_string;,确保所有非静态请求兜底到入口文件 - 别用
rewrite ^/(.*)$ /index.php/$1 last;:旧式写法容易循环重定向,且 PHP 无法从$_SERVER['PATH_INFO']正确提取路径 - 如果部署在子目录(如
https://example.com/app/),location必须带前缀,try_files中的/index.php得改成/app/index.php -
root必须指向public/目录,不是项目根目录;否则$document_root/index.php就是错的路径
多语言 URL 如何重写?ThinkPHP 不需要特殊 Nginx 规则
ThinkPHP 的多语言切换(比如 zh-CN、en-US)靠的是路由参数或中间件识别 Accept-Language、URL 前缀、Cookie 等,**Nginx 层不需要为语言加额外重写规则**。
- 若用 URL 前缀方式(如
/zh-CN/user/login),只要保证整个请求仍被try_files推给index.php,框架就能从$_SERVER['REQUEST_URI']解析出完整路径 - 别试图在 Nginx 里做语言跳转(比如
rewrite ^/zh-CN/(.*)$ /$1 break;),这会破坏路由上下文,导致url()生成错误链接 - 确保
fastcgi_param REQUEST_URI $request_uri;存在,否则框架看到的 URI 是重写前的,语言前缀会丢失
SCRIPT_FILENAME 报 “No input file specified” 怎么修?
这是最典型的 500 错误,本质是 PHP-FPM 收到了一个不存在或权限不对的文件路径。
立即学习“PHP免费学习笔记(深入)”;
- 检查
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;—— 这行必须存在,且不能写死成/var/www/app/public/index.php - 确认
root和$document_root一致:比如root /data/app/public;,那$document_root/index.php就得真实存在 - 运行
ls -l /data/app/public/index.php,确保 Nginx 用户(如www-data)有读权限 - 检查 PHP-FPM 的
security.limit_extensions是否包含.php(有些 Docker 镜像会删掉)
PATH_INFO 模式(url_model => 2)还值得配吗?
不推荐。ThinkPHP 6.x 默认走 QUERY_STRING 模式(?s=/user/list),更稳定、兼容性更好;PATH_INFO 在 Nginx 下需额外配置 fastcgi_split_path_info,稍有不慎就 404 或变量为空。
- 如果真要用 PATH_INFO,必须加这两行:
fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_param PATH_INFO $fastcgi_path_info;
- 但要注意:Nginx 的
if (!-e $request_filename)块和fastcgi_split_path_info不能混用,前者已被证明在某些版本下不可靠 - 更稳妥的做法是框架内保持
url_model => 0(兼容模式)或1(普通模式),Nginx 只管把请求交过去
真正卡住人的,往往不是要不要配多语言,而是 root 指向错了一级、try_files 少了个 ?、或者 SCRIPT_FILENAME 里漏了 $document_root —— 这些细节一错,整个路由链就断了。

