0

0

Nginx URI重写教程:剥离子目录实现灵活路由

碧海醫心

碧海醫心

发布时间:2025-09-25 11:43:09

|

726人浏览过

|

来源于php中文网

原创

Nginx URI重写教程:剥离子目录实现灵活路由

本教程详细讲解如何在Nginx中实现URI重写,以剥离特定子目录(如/shop)并将其后续路径作为参数传递给后端PHP脚本(如main.php)。通过结合try_files和rewrite指令,本教程提供了一种高效且结构清晰的解决方案,旨在帮助用户在Nginx环境中构建类似Apache mod_rewrite的灵活路由机制,避免常见的配置陷阱。

1. 理解URI重写需求

在基于php-fpm的应用中,常见的一种路由模式是将所有请求都导向一个前端控制器(如index.php或main.php),然后由该控制器根据uri路径来决定加载哪个模块或页面。当应用部署在nginx的某个子目录(例如/shop)下时,我们可能希望将形如 example.com/shop/product/123 的请求内部转换为 example.com/shop/main.php?route=/product/123。这要求nginx能够:

  1. 识别以 /shop 开头的请求。
  2. 从URI中剥离 /shop 部分。
  3. 将剥离后的路径作为 route 参数传递给 main.php。
  4. 优先处理静态文件,如果请求的URI对应文件或目录存在,则直接提供服务。

2. 常见误区与Nginx指令解析

在尝试实现上述需求时,一些常见的错误配置方法及其原因如下:

  • 错误地在 try_files 中使用 $1 变量:

    location ^~ /shop/product {
        try_files $uri $uri/ @rewrite;
    }
    location @rewrite {
        try_files $uri $uri/ /shop/main.php?route=$1 ; # 这里的 $1 是无效的
    }

    $1 等捕获组变量仅在 rewrite 指令中,通过正则表达式匹配后才能被赋值。try_files 指令的主要作用是按顺序检查文件或目录是否存在,并提供回退机制,它不具备正则表达式匹配和捕获组赋值的能力。因此,在 try_files 中直接使用 $1 会导致变量未定义,通常表现为404错误。

  • 直接使用 $uri 作为参数:

    location /shop {
        try_files $uri $uri/ /shop/main.php?route=$uri;
    }

    这种方式会将完整的URI(例如 /shop/product/123)作为 route 参数传递,而不是我们期望的 /product/123。这不符合剥离子目录的需求。

要正确实现URI重写,我们需要利用Nginx的 rewrite 指令,它专门用于基于正则表达式进行URI转换。

3. Nginx URI重写解决方案

以下是实现上述路由需求的Nginx配置示例:

AI帮个忙
AI帮个忙

多功能AI小工具,帮你快速生成周报、日报、邮、简历等

下载
server {
    listen 80;
    server_name example.com;
    root /var/www/html; # 你的项目根目录,main.php 位于 /var/www/html/shop/main.php

    index index.php index.html;

    # PHP-FPM 配置(示例,请根据实际情况调整)
    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php7.4-fpm.sock; # 或 fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    # 核心URI重写逻辑
    location /shop/ {
        # 1. 尝试直接提供静态文件或目录
        # 如果 /var/www/html/shop/product/123 存在文件或目录,则直接服务
        try_files $uri $uri/ @rewrite_shop;
    }

    # 2. 定义一个命名location来处理重写逻辑
    location @rewrite_shop {
        # 使用 rewrite 指令进行URI转换
        # ^/shop(/.*) : 匹配以 /shop 开头,并捕获 /shop 之后的所有内容到 $1
        # /shop/main.php?route=$1 : 重写目标,将捕获的 $1 作为 route 参数
        # last : 停止当前 location 的处理,并用新URI重新进行 location 匹配
        rewrite ^/shop(/.*) /shop/main.php?route=$1 last;
    }

    # 阻止访问 .htaccess 文件(如果存在,虽然Nginx不使用)
    location ~ /\.ht {
        deny all;
    }
}

4. 配置详解

  1. location /shop/ { ... }:

    • 这个 location 块用于匹配所有以 /shop/ 开头的URI请求。
    • try_files $uri $uri/ @rewrite_shop;:这是Nginx处理请求的推荐方式。它会按顺序执行以下操作:
      • $uri:尝试查找与当前URI完全匹配的文件。例如,对于 /shop/style.css,它会尝试查找 /var/www/html/shop/style.css。
      • $uri/:如果 $uri 不是文件但存在同名目录,Nginx会尝试查找该目录下的 index 文件(由 index 指令定义,如 index.php)。
      • @rewrite_shop:如果前两者都未找到,则将请求内部重定向到名为 @rewrite_shop 的命名 location 块进行处理。
  2. location @rewrite_shop { ... }:

    • 这是一个命名 location 块,它不能直接匹配外部请求,只能通过 try_files 或其他内部重定向指令引用。
    • rewrite ^/shop(/.*) /shop/main.php?route=$1 last;:这是实现核心重写逻辑的关键。
      • rewrite:Nginx的重写指令。
      • ^/shop(/.*):一个正则表达式。
        • ^:匹配URI的开始。
        • /shop:字面匹配 /shop。
        • (/.*):捕获组。.* 匹配除换行符外的任何字符零次或多次。括号 () 将匹配到的内容捕获到 $1 变量中。这意味着,如果URI是 /shop/product/123,那么 $1 将是 /product/123。
      • /shop/main.php?route=$1:重写后的目标URI。$1 会被正则表达式捕获到的内容替换。
      • last:这是一个标志位。它告诉Nginx停止处理当前的 rewrite 指令集,并用新生成的URI(/shop/main.php?route=/product/123)重新开始 location 匹配过程。这意味着新的URI会再次被Nginx的 location 块进行匹配,最终可能会被 location ~ \.php$ 块捕获并传递给PHP-FPM处理。

5. 与Apache .htaccess 的对比

Apache的 .htaccess 文件中的 RewriteRule (.*) main.php?route=$1 规则通常在 RewriteBase /shop 的上下文中使用,或者通过 RewriteRule ^shop/(.*) shop/main.php?route=$1 实现类似效果。

Nginx的 rewrite 指令与Apache的 mod_rewrite 具有相似的功能,但工作方式略有不同。Nginx的配置是集中式的,通常在 server 块中定义,而Apache的 .htaccess 允许分布式配置。Nginx的 last 标志在功能上类似于Apache的 [L] (Last) 标志,都表示停止当前规则集的处理并重新开始URI匹配。

6. 注意事项与最佳实践

  • 性能优化: 尽可能使用 try_files 来直接服务静态文件,只有在文件不存在时才进行重写,这样可以减少PHP-FPM的负载。
  • 正则表达式准确性: 确保 rewrite 指令中的正则表达式准确匹配你想要转换的URI部分,并正确捕获所需参数。
  • last vs break vs redirect:
    • last:停止当前 location 的处理,用新URI重新进行 location 匹配。适用于内部重写,通常是期望将请求传递给另一个 location 块(如PHP处理器)。
    • break:停止当前 location 的 rewrite 指令处理,但继续在该 location 块内处理其他指令。不推荐用于复杂的路由场景。
    • redirect:返回一个302临时重定向响应给客户端,浏览器会用新URI发起新的请求。适用于外部可见的URL变更。
    • permanent:返回一个301永久重定向响应。 在本例中,last 是最合适的选择,因为它实现了内部重写,对客户端透明,并允许Nginx继续处理重写后的URI。
  • PHP-FPM配置: 确保你的 location ~ \.php$ 块配置正确,能够将重写后的PHP脚本(如 /shop/main.php)传递给PHP-FPM处理。fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 是关键,它确保PHP-FPM知道要执行哪个脚本文件。

7. 总结

通过本教程,我们学习了如何在Nginx中利用 location、try_files 和 rewrite 指令,高效且准确地实现URI重写,以剥离子目录并传递动态路由参数。这种方法不仅解决了特定场景下的路由需求,也展示了Nginx在处理复杂URI逻辑方面的强大能力和灵活性。理解这些核心指令及其配合使用方式,对于构建高性能、可维护的Nginx应用至关重要。

相关专题

更多
php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

1703

2023.09.01

php怎么取出数组的前几个元素
php怎么取出数组的前几个元素

取出php数组的前几个元素的方法有使用array_slice()函数、使用array_splice()函数、使用循环遍历、使用array_slice()函数和array_values()函数等。本专题为大家提供php数组相关的文章、下载、课程内容,供大家免费下载体验。

1129

2023.10.11

php反序列化失败怎么办
php反序列化失败怎么办

php反序列化失败的解决办法检查序列化数据。检查类定义、检查错误日志、更新PHP版本和应用安全措施等。本专题为大家提供php反序列化相关的文章、下载、课程内容,供大家免费下载体验。

1033

2023.10.11

php怎么连接mssql数据库
php怎么连接mssql数据库

连接方法:1、通过mssql_系列函数;2、通过sqlsrv_系列函数;3、通过odbc方式连接;4、通过PDO方式;5、通过COM方式连接。想了解php怎么连接mssql数据库的详细内容,可以访问下面的文章。

948

2023.10.23

php连接mssql数据库的方法
php连接mssql数据库的方法

php连接mssql数据库的方法有使用PHP的MSSQL扩展、使用PDO等。想了解更多php连接mssql数据库相关内容,可以阅读本专题下面的文章。

1396

2023.10.23

html怎么上传
html怎么上传

html通过使用HTML表单、JavaScript和PHP上传。更多关于html的问题详细请看本专题下面的文章。php中文网欢迎大家前来学习。

1228

2023.11.03

PHP出现乱码怎么解决
PHP出现乱码怎么解决

PHP出现乱码可以通过修改PHP文件头部的字符编码设置、检查PHP文件的编码格式、检查数据库连接设置和检查HTML页面的字符编码设置来解决。更多关于php乱码的问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1439

2023.11.09

php文件怎么在手机上打开
php文件怎么在手机上打开

php文件在手机上打开需要在手机上搭建一个能够运行php的服务器环境,并将php文件上传到服务器上。再在手机上的浏览器中输入服务器的IP地址或域名,加上php文件的路径,即可打开php文件并查看其内容。更多关于php相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1303

2023.11.13

虚拟号码教程汇总
虚拟号码教程汇总

本专题整合了虚拟号码接收验证码相关教程,阅读下面的文章了解更多详细操作。

25

2025.12.25

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Sass 教程
Sass 教程

共14课时 | 0.7万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 2.6万人学习

CSS教程
CSS教程

共754课时 | 16.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号