URL重写由Web服务器(Apache/Nginx)实现,PHP仅处理重写后的请求;需正确配置服务器模块、.htaccess或server块,注意正则语法、标志位、PATH_INFO与QUERY_STRING差异,并逐层调试$_SERVER变量。

PHP本身不直接处理URL重写,真正起作用的是Web服务器(Apache或Nginx)的重写模块;PHP只是接收重写后传来的参数并响应。搞不清这点,就容易在index.php里徒劳地写路由逻辑,却忘了配服务器。
Apache下启用mod_rewrite并验证是否生效
先确认mod_rewrite已加载:运行phpinfo(),搜索“Loaded Modules”,看是否有mod_rewrite。没有的话,打开httpd.conf,取消注释这行:
LoadModule rewrite_module modules/mod_rewrite.so
再确保.htaccess能被读取:找到<Directory ""/var/www/html"">(路径按你实际调整)区块,把AllowOverride None改成AllowOverride All,然后重启Apache。
- 改完不重启,规则永远不生效
- 如果用XAMPP/MAMP,可能需额外勾选“rewrite module”开关
- 部分共享主机禁用
AllowOverride All,此时只能让服务商帮你改主配置
写.htaccess时最常踩的三个坑
.htaccess文件名必须严格为.htaccess(开头带点,无后缀),Windows下不能直接新建,得用记事本“另存为”并手动输入".htaccess"(含英文引号)或者用命令行rename htaccess.txt .htaccess。
立即学习“PHP免费学习笔记(深入)”;
常见错误规则示例:
RewriteEngine On RewriteRule ^article/(\d+)$ article.php?id=$1 [L]
- 忘记
RewriteEngine On——整段规则静默失效 - 正则里用
(\d+)但Apache 2.2以下版本不支持\d,得写成([0-9]+) - 漏掉
[L]标志,导致后续规则意外触发,比如静态资源.css也被重写 -
RewriteBase没设对:子目录部署时(如example.com/blog/),要加RewriteBase /blog/,否则$1会拼错路径
Nginx配置等效写法与关键差异
Nginx没有.htaccess机制,所有规则必须写进server块。典型写法:
location / {
try_files $uri $uri/ @rewrite;
}
location @rewrite {
rewrite ^/article/([0-9]+)$ /article.php?id=$1 last;
}
注意几点:
-
try_files是核心:它先尝试找真实文件(如/style.css),找不到才进@rewrite,避免CSS/JS被误重写 - Apache的
[L]对应Nginx的last,而break会停止重写但不重新匹配location - Nginx正则默认区分大小写,要忽略大小写得加
~*前缀,如rewrite ^/ARTICLE/([0-9]+)$ ...需写成rewrite ^/article/([0-9]+)$ ...或用~* - PHP-FPM转发必须存在,否则
article.php返回源码而非执行结果
重写后$_GET参数拿不到?检查PATH_INFO和QUERY_STRING
有些规则(如RewriteRule ^post/([0-9]+)/?$ index.php/post/$1 [L])会让PHP收到$_SERVER['PATH_INFO']而非$_GET。这时不能只依赖$_GET['id']。
- 统一用
parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)提取路径再解析,更可靠 - Apache下可加
RewriteCond %{QUERY_STRING} ^(.*)$再RewriteRule透传查询参数 - 开发时用
var_dump($_SERVER['REQUEST_URI'], $_GET, $_SERVER['PATH_INFO'])立刻看清数据在哪 - 别在重写规则里拼
?和&——Nginx用?$args,Apache用%{QUERY_STRING},手写易出编码问题
真正的难点不在写几行规则,而在于理解请求如何从浏览器地址栏,经服务器重写、路径解析、PHP入口分发,最终落到某个变量上。每层都可能吃掉一部分信息,调试时得一层层var_dump出来看,而不是凭感觉猜。



















