但是当我转到 URL http://localhost/prezzo/account/1 并加载 test.php [...] 时,它返回字符串“php”而不是“1”。
是的,这是所发布的规则所期望的。
这似乎在“htaccess 测试器”中工作,因为该工具只对文件进行一次传递,这不是真实服务器的工作方式。
RewriteRule (\w+)/?$ test.php?user=$1 [L]
当您请求/prezzo/account/1 时...
- 请求被重写为
test.php?user=1
-
L 标志使重写引擎使用重写后的 URL (test.php?user=1) 作为下一轮处理的输入重新开始。
- 请求被重写为
test.php?user=php,因为正则表达式(\w+)/?$ 捕获了test.php 的php 部分。 (\w 速记字符类不包括点且正则表达式未锚定。)
-
L 标志使重写引擎使用重写的 URL (test.php?user=php) 作为下一轮处理的输入重新开始。
- 请求被重写为
test.php?user=php(再次)。
- 由于 URL 未更改通过,重写过程停止,请求最终被重写为
/test.php?user=php。
解决方案 A - 使用 END 标志
一种解决方案是简单地使用END 标志(Apache 2.4)而不是L 来防止重写引擎“循环”。一旦指令被处理,它将立即停止。例如:
RewriteRule (\w+)/?$ test.php?user=$1 [END]
解决方案 B - 使正则表达式更具体
另一个解决方案(或以及)是使正则表达式更具体,使其与test.php 不匹配。 IE。只匹配您期望的 URL 格式。
正则表达式 (\w+)/?$ 似乎过于通用,因为它基本上只是匹配 URL 路径上的最后一组字母/数字。如果您只想匹配数字(“用户 ID”),那么您可以使正则表达式更具限制性并仅匹配数字。
您还应该在开头锚定正则表达式,以便它匹配整个路径段,而不是仅捕获匹配的最后一部分。事实上,简单地锚定上述正则表达式也可以解决这个问题,因为test.php 将无法匹配,因为\w 不匹配点。
例如:
RewriteRule ^(\d+)/?$ test.php?user=$1 [L]
这将只匹配最后一个路径段中的数字。
如果我尝试
RewriteRule ^prezzo/account/(\w+)/?$ prezzo/account/test.php?user=$1 [L]
我得到 404 not found 虽然 htaccess 测试器报告该规则是
正确应用并重写 URL
如果.htaccess 文件位于/prezzo/account 子目录中(如您所说),则上述内容将永远不会匹配,并且该指令什么也不做。
该测试工具假定.htaccess 文件仅位于文档根目录中。如果您的 .htaccess 位于文档根目录而不是子目录中,那么该指令确实可以。
在目录上下文(例如.htaccess)中,RewriteRule 模式与目录的相对 URL路径匹配包含.htaccess 文件。
旁白:
在您的链接中,整个文件似乎是:
RewriteEngine On
#RewriteCond %{REQUEST_FILENAME} !-f
#RewriteCond %{REQUEST_FILENAME} !-d
#RewriteCond %{REQUEST_FILENAME} !-l
#RewriteRule . index.php [L]
RewriteRule (\w+)/?$ test.php?user=$1 [L]
第一条规则被注释掉,所以这里不适用。但是,如果您取消注释第一条规则,则规则的顺序错误。因为/prezzo/account/1 的请求首先会被重写为index.php,你会遇到和以前一样的问题。
规则的顺序很重要。