如果您希望 /post/3/users/ 转到 /Users.php?id=3,则必须将该规则放在现有规则之前。您现有的规则与 /post/3/' 匹配,这是此附加规则匹配的前缀,因此该规则在之后将永远不会触发。
# catch the longer URL first
RewriteRule ^post/([A-Za-z0-9-]+)/users/?$ Users.php?id=$1 [NC,L]
# No /users/ on it; rewrite to post.php
RewriteRule ^post/([A-Za-z0-9-]+)/?$ post.php?id=$1 [NC,L]
另一件事:您用.htaccess 标记了您的帖子。这是否意味着您的重写在.htaccess 中?如果是这样,您应该使用RewriteBase,因为您的重写是相对的。它之所以起作用,可能是因为您允许网络服务器上的路径和 URL 之间存在 1:1 的对应关系。
在像.htaccess 这样的每个目录上下文中,mod_rewrite 使用的是路径名,而不是 URL。但是如果你进行相对重写,路径会变成一个 URL 并反馈到 Apache 的请求处理链中以重新处理。路径怎么变成URL是把RewriteBase的内容加到前面。如果您没有RewriteBase,那么会发生一件愚蠢的事情:您的目录路径(为RewriteRule 删除的路径被重新添加了!)。
示例:假设您的 DocumentRoot 是 /var/www。假设浏览器请求 URL /foo。这将被转换为路径/var/www/foo 如果在/var/www/ 的.htaccess 内将foo 重写为bar(并且未设置RewriteBase),那么mod_rewrite 将生成URL /var/www/bar:它只是获取被剥离的/var/www/ 目录并将其重新打开。现在可以让它工作了:只需让/var/www/ 成为一个有效的URL 去那个目录。例如与
Alias /var/www /var/www # map /var/www URL to /var/www directory
但那太老套了。正确的方法是在.htaccess 中有RewriteBase /。所以当foo被重写为bar时,它只是在前面多了一个/,变成了url/bar。这会反馈给服务器,并会“自然”地再次解析回文档根目录。
在我理解重写之前,我使用过类似的技巧。我什至用/ 作为DocumentRoot!从那时起,一切都顺利进行了,大多数 URL 都是路径:您不必将 URL 视为与文件系统路径分开的抽象。但这是一件危险而愚蠢的事情。