如何设置Nginx以适配ThinkPHP的URL重写规则?
- 内容介绍
- 文章标签
- 相关推荐
本文共计973个文字,预计阅读时间需要4分钟。
如果您已经将ThinkPHP项目部署至Nginx服务器,但在访问时发现无需携带index.,可能的原因如下:
一、标准try_files方案(推荐用于ThinkPHP 6.x)
该方案利用try_files指令实现原子化路径匹配,避免rewrite循环,兼容QUERY_STRING传递,是TP6官方推荐方式。它优先尝试匹配真实静态资源,失败后统一交由index.php处理,并保留原始查询参数。
1、编辑站点server块,在location /内添加以下规则:
2、try_files $uri $uri/ /index.php?$query_string;
立即学习“PHP免费学习笔记(深入)”;
3、确保location ~ \.php$块中fastcgi_param SCRIPT_FILENAME值为$document_root$fastcgi_script_name,严禁使用$request_filename。
4、确认PHP-FPM监听地址与fastcgi_pass配置一致(如unix:/var/run/php/php8.1-fpm.sock或127.0.0.1:9000)。
二、PATH_INFO兼容方案(适用于ThinkPHP 5.1及启用pathinfo模式的场景)
当应用配置了'url_model' => 2(PATH_INFO模式)或需兼容旧路由格式(如/index.php/Index/index)时,必须显式提取并传递PATH_INFO变量,否则$_SERVER['PATH_INFO']为空,路由解析失败。
1、在location /块中使用if判断+rewrite组合:
2、if (!-e $request_filename) { rewrite ^(.*)$ /index.php?s=$1 last; }
3、在location ~ \.php$块中添加PATH_INFO支持指令:
4、fastcgi_split_path_info ^(.+\.php)(/.+)$;
5、fastcgi_param PATH_INFO $fastcgi_path_info;
6、必须同时设置fastcgi_param SCRIPT_NAME $fastcgi_script_name,否则$_SERVER['SCRIPT_NAME']异常影响URL生成。
三、子目录部署适配方案(如部署在https://example.com/app/下)
当ThinkPHP未部署在域名根路径,而是位于子目录(如/app/)时,Nginx需识别前缀并剥离后将剩余URI传递给框架,否则Route::rule()无法匹配定义的路由规则。
1、定义带前缀的location块:location /app/ {
2、在该块内使用try_files并指定入口相对路径:try_files $uri $uri/ /app/index.php?$query_string;
3、修改root指令指向网站根目录(非子目录),例如root /var/www/html;,确保$document_root/app/index.php可被定位。
4、所有rewrite目标路径必须以/app/开头,且正则捕获组需排除前缀,例如rewrite ^/app/(.*)$ /app/index.php?s=/$1 last;。
四、安全增强型配置组合(禁用敏感路径+隐藏文件)
除重写功能外,必须同步限制对框架敏感目录的Web直接访问,防止.env、runtime、config等目录泄露,这是生产环境强制要求。
1、在server块中添加独立location规则屏蔽敏感目录:
2、location ~ ^/(app|config|database|runtime|vendor|extend)/ { deny all; }
3、添加隐藏文件禁止访问规则:
4、location ~ /\. { deny all; }
5、特别注意:.env文件必须被deny,否则数据库密码等关键信息将完全暴露。
五、调试与验证步骤
配置修改后需逐项验证是否生效,避免因语法错误或缓存导致误判。Nginx配置变更必须重载而非仅重启,且需确认PHP-FPM服务处于运行状态。
1、执行nginx -t检查配置语法是否正确,输出'syntax is ok'且'test is successful'才可继续。
2、执行nginx -s reload平滑重载配置,不中断现有连接。
3、创建测试路由(如route/app.php中添加Route::get('test-rewrite', function(){ return 'success'; });)。
4、访问https://example.com/test-rewrite,若返回'success'且URL中无index.php,则重写成功;若返回404,检查error.log中是否有FastCGI sent in stderr: "Primary script unknown"类错误。
本文共计973个文字,预计阅读时间需要4分钟。
如果您已经将ThinkPHP项目部署至Nginx服务器,但在访问时发现无需携带index.,可能的原因如下:
一、标准try_files方案(推荐用于ThinkPHP 6.x)
该方案利用try_files指令实现原子化路径匹配,避免rewrite循环,兼容QUERY_STRING传递,是TP6官方推荐方式。它优先尝试匹配真实静态资源,失败后统一交由index.php处理,并保留原始查询参数。
1、编辑站点server块,在location /内添加以下规则:
2、try_files $uri $uri/ /index.php?$query_string;
立即学习“PHP免费学习笔记(深入)”;
3、确保location ~ \.php$块中fastcgi_param SCRIPT_FILENAME值为$document_root$fastcgi_script_name,严禁使用$request_filename。
4、确认PHP-FPM监听地址与fastcgi_pass配置一致(如unix:/var/run/php/php8.1-fpm.sock或127.0.0.1:9000)。
二、PATH_INFO兼容方案(适用于ThinkPHP 5.1及启用pathinfo模式的场景)
当应用配置了'url_model' => 2(PATH_INFO模式)或需兼容旧路由格式(如/index.php/Index/index)时,必须显式提取并传递PATH_INFO变量,否则$_SERVER['PATH_INFO']为空,路由解析失败。
1、在location /块中使用if判断+rewrite组合:
2、if (!-e $request_filename) { rewrite ^(.*)$ /index.php?s=$1 last; }
3、在location ~ \.php$块中添加PATH_INFO支持指令:
4、fastcgi_split_path_info ^(.+\.php)(/.+)$;
5、fastcgi_param PATH_INFO $fastcgi_path_info;
6、必须同时设置fastcgi_param SCRIPT_NAME $fastcgi_script_name,否则$_SERVER['SCRIPT_NAME']异常影响URL生成。
三、子目录部署适配方案(如部署在https://example.com/app/下)
当ThinkPHP未部署在域名根路径,而是位于子目录(如/app/)时,Nginx需识别前缀并剥离后将剩余URI传递给框架,否则Route::rule()无法匹配定义的路由规则。
1、定义带前缀的location块:location /app/ {
2、在该块内使用try_files并指定入口相对路径:try_files $uri $uri/ /app/index.php?$query_string;
3、修改root指令指向网站根目录(非子目录),例如root /var/www/html;,确保$document_root/app/index.php可被定位。
4、所有rewrite目标路径必须以/app/开头,且正则捕获组需排除前缀,例如rewrite ^/app/(.*)$ /app/index.php?s=/$1 last;。
四、安全增强型配置组合(禁用敏感路径+隐藏文件)
除重写功能外,必须同步限制对框架敏感目录的Web直接访问,防止.env、runtime、config等目录泄露,这是生产环境强制要求。
1、在server块中添加独立location规则屏蔽敏感目录:
2、location ~ ^/(app|config|database|runtime|vendor|extend)/ { deny all; }
3、添加隐藏文件禁止访问规则:
4、location ~ /\. { deny all; }
5、特别注意:.env文件必须被deny,否则数据库密码等关键信息将完全暴露。
五、调试与验证步骤
配置修改后需逐项验证是否生效,避免因语法错误或缓存导致误判。Nginx配置变更必须重载而非仅重启,且需确认PHP-FPM服务处于运行状态。
1、执行nginx -t检查配置语法是否正确,输出'syntax is ok'且'test is successful'才可继续。
2、执行nginx -s reload平滑重载配置,不中断现有连接。
3、创建测试路由(如route/app.php中添加Route::get('test-rewrite', function(){ return 'success'; });)。
4、访问https://example.com/test-rewrite,若返回'success'且URL中无index.php,则重写成功;若返回404,检查error.log中是否有FastCGI sent in stderr: "Primary script unknown"类错误。

