
在基于php-fpm的应用中,常见的一种路由模式是将所有请求都导向一个前端控制器(如index.php或main.php),然后由该控制器根据uri路径来决定加载哪个模块或页面。当应用部署在nginx的某个子目录(例如/shop)下时,我们可能希望将形如 example.com/shop/product/123 的请求内部转换为 example.com/shop/main.php?route=/product/123。这要求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转换。
以下是实现上述路由需求的Nginx配置示例:
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;
}
}location /shop/ { ... }:
location @rewrite_shop { ... }:
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匹配。
通过本教程,我们学习了如何在Nginx中利用 location、try_files 和 rewrite 指令,高效且准确地实现URI重写,以剥离子目录并传递动态路由参数。这种方法不仅解决了特定场景下的路由需求,也展示了Nginx在处理复杂URI逻辑方面的强大能力和灵活性。理解这些核心指令及其配合使用方式,对于构建高性能、可维护的Nginx应用至关重要。
以上就是Nginx URI重写教程:剥离子目录实现灵活路由的详细内容,更多请关注php中文网其它相关文章!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号