我同意 Walf 的观点,即通过路由器类处理路由比使用 .htaccess 重定向更好(尤其是从长远来看!)。
但是,由于您的问题似乎更多地是关于为什么这不起作用而不是关于您应该如何做,所以这里是对正在发生的事情的解释。
我将使用这些 URL 作为示例:
localhost:8080
localhost:8080/app
localhost:8080/app/customers/id/5
你的第一条规则:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{HTTP_HOST} ^(www.)?localhost:8080$
RewriteRule ^(.*)$ /views/$1
如您所愿,此 RewriteRule 将匹配任何不是文件、不是目录且位于 localhost:8080 的 URL。
localhost:8080 # not matched because it leads to a directory.
localhost:8080/app -> localhost:8080/views/app
localhost:8080/app/customers/id/5 -> localhost:8080/views/app/customers/id/5
你的下一条规则:
RewriteRule ^(/)?$ /views/index.php [L]
重要的是要意识到 RewriteCond 语句仅适用于它们之后的第一个 RewriteRule,因此这里检查的只是路径。
旁注:^(/)?$,因为你没有使用$1,可以简化为^/?$。
localhost:8080 -> localhost:8080/views/index.php
localhost:8080/views/app # not matched
localhost:8080/views/app/customers/id/5 # not matched
由于指定了L 标志,Apache 将立即停止当前的迭代,并从顶部重新开始匹配。 The documentation is badly worded。因此,localhost:8080/views/index.php 将通过第一条规则运行,匹配失败,通过这条规则运行,匹配失败,然后由于不存在其他规则来检查(但)不会进行重写。
现在让我们看看当您添加损坏的规则时会发生什么。
RewriteRule /id/(.*) customers.php?id=$1
这里有一些问题。首先,由于您不要求 URL 以 /id/ 开头,因此该规则将始终匹配包含 /id/ 的 URL,即使您已经重写了 URL。如果您使用^/id/(.*) 对此进行了修改,那么您仍然会遇到问题,因为测试重写 RegEx 的字符串已删除前导斜杠。最后也是最重要的一点,customers.php 不存在于您的根目录中。
localhost:8080/views/index.php # not matched
localhost:8080/views/app # not matched
localhost:8080/views/app/customers/id/5 -> localhost:8080/customers.php?id=5
这是当前文件中的最后一条规则,因此现在 Apache 将重新开始。 customers.php在你的目录中不存在,所以会被重写为views/customers.php。没有匹配其他规则,但 URL 已更改,因此 Apache 将重新开始,因为 /views/customers.php 不存在,它将被重写为 /views/views/customers.php ...此模式将重复,直到您达到最大迭代限制和 Apache以 500 错误响应。
您可以通过多种方式解决此问题。这是我的首选方法,但前提是您不能使用路由器。
RewriteEngine on
# Rewrite the main page, even though it is a directory
RewriteRule ^/?$ views/index.php [END]
# Don't rewrite any existing files or directories
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .? - [S=999,END]
RewriteRule ^app/?$ views/app/index.php [END]
RewriteRule ^app/id/(.*)$ views/app/customers.php?id=$1 [END]
TL;DR 使用基于 PHP 的路由器。 .htaccess 规则可能令人难以置信的混乱。