使用.htaccess在PHP中重写动态URL及获取ID参数求助
实现URL重写:动态链接转友好静态URL
我来帮你搞定这个URL重写的问题,先理清楚你的需求和之前尝试里的小问题,再给出靠谱的解决方案。
你的核心需求回顾
- 原始动态URL:
xyz.com/news_details.php?id=120&title=hello-world - 期望的友好静态URL:
xyz.com/hello-world - 关键要求:在
news_details.php页面里依然能通过$id = $_REQUEST['id'];获取到id值
你之前尝试的问题点
你写的规则有几个小纰漏:
- 捕获组索引错误——用了
%2但只定义了一个捕获组,匹配逻辑不对 - 正则匹配范围太窄——
[^&\s]只能匹配单个字符,没法完整捕获id或title值 - 规则顺序和逻辑有问题——应该先处理外部重定向(让旧URL跳转到新URL),再处理内部转发(把新URL映射回原PHP文件)
解决方案:分两种场景处理
这里要注意一个关键:友好URLxyz.com/hello-world里并没有包含id信息,所以直接通过重写规则没法把id传递给PHP,得选合适的方案:
方案1:调整友好URL格式,包含id(推荐,更直接)
把友好URL改成xyz.com/120-hello-world,这样既能保持URL友好,又能直接提取id,规则如下:
# 1. 外部重定向:把旧的动态URL永久跳转到新的友好URL RewriteCond %{THE_REQUEST} /news_details\.php\?id=(\d+)&title=([^\s&]+) [NC] RewriteRule ^ /%1-%2? [R=301,L,NE] # 2. 内部重写:把友好URL映射回原PHP文件,自动传递id和title参数 RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(\d+)-([^\s/]+)$ /news_details.php?id=$1&title=$2 [L,QSA]
这样设置后,访问xyz.com/120-hello-world时,PHP里就能直接用$_REQUEST['id']拿到120,完全满足你的需求。
方案2:保持友好URL仅含title,通过PHP查询获取id
如果一定要坚持友好URL只有hello-world,那需要在PHP里通过title去数据库查询对应的id,重写规则调整为:
# 1. 外部重定向:旧URL转新URL RewriteCond %{THE_REQUEST} /news_details\.php\?id=(\d+)&title=([^\s&]+) [NC] RewriteRule ^ /%2? [R=301,L,NE] # 2. 内部重写:把友好URL映射回原PHP文件,传递title参数 RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^([^\s/]+)$ /news_details.php?title=$1 [L,QSA]
然后在news_details.php里添加查询逻辑(假设你的新闻表是news,且title字段唯一):
$title = $_REQUEST['title']; // 这里要注意防止SQL注入,建议用预处理语句 $stmt = $pdo->prepare("SELECT id FROM news WHERE title = ?"); $stmt->execute([$title]); $news = $stmt->fetch(PDO::FETCH_ASSOC); $id = $news['id'] ?? null;
这种方案要求title字段在数据库中唯一,否则会出现匹配错误。
注意事项
- 确保Apache服务器已经开启
mod_rewrite模块 .htaccess文件要放在网站根目录下R=301是永久重定向,有利于SEO;测试阶段可以先用R=302临时重定向NE标志用于防止URL中的特殊字符被编码,保持title的原样显示
内容的提问来源于stack exchange,提问作者swap




