我正在尝试做很多人以前做过很多次的事情,但我似乎无法让它发挥作用。我已经尝试了将近 2 天,我一直在互联网上搜索一个工作示例,发现了许多非常相似的 SO 问题,但没有一个对我有用 - 其中大多数都在使用键/值方法,我只是想要值列表。
我想要的是:
我希望能够使用搜索引擎友好的 URL。由于相关站点当前工作方式的性质,我想转换此请求 URI:
/this/is/a/随机/路径
...到:
/index.php?p[]=this&p[]=is&p[]=a&p[]=random&p[]=path
这样当它到达 PHP 时,它将作为$_GET['p']
. 我也希望它也能容忍斜杠,所以我会得到相同的结果:
/this/is/a/随机/路径/
我是如何尝试这样做的:
我对正则表达式还不错,而且我对 mod_rewrite 的工作原理有合理的理解,但我认为我已经消失在错误的道路上,以至于我再也看不到回去的路了。
这是我目前拥有的:
# 打开 mod_rewrite 重写引擎开启 # 允许直接加载 /static 目录中的文件 RewriteCond %{REQUEST_FILENAME} -f 重写规则 ^/?static/(.+)$ - [L] # 递归捕获所有路径组件 RewriteCond %{REQUEST_URI} !^/?(?:index\.php)?$ 重写规则 ^/?([^/]+)(?:/(.+)$|/?$) $2?p[]=$1 [QSA,L] # 向控制器发送请求 重写规则 ^.*$ index.php [QSA]
怎么了:
第一个RewriteCond
/RewriteRule
对工作得很好 - 如果我请求目录中存在的文件,/static
则请求保持原样并提供文件。如果该文件不存在,则它属于第二组规则,以便我可以显示我的一个性感的基于 PHP 的错误页面。
问题在于第二个RewriteCond
/RewriteRule
对,也可能是第三个RewriteRule
。该条件应该存在以确保最终迭代不会导致将脚本名称添加到数组中-这似乎有效。这就是我认为第二个RewriteRule
正在做的事情,我怀疑我在这里错过了一些明显的东西:
^/? # 以可选的斜杠开头的字符串 ([^/]+) # 捕获直到下一个斜杠的所有字符 (?:/(.+)$|/?$) # 要么抓取下一个斜杠之后的所有字符,要么匹配结尾 $2?p[]=$1 # 将捕获的路径组件推送到数组中,并将 URI 下移 [QSA,L] # 合并上一个查询字符串,继续下一次迭代
这是 90% 的工作。我遇到的问题:
- 数组组件的顺序是相反的。我理解为什么会这样,并且我意识到这可能是不可避免的,在 PHP 中使用
array_reverse()
. 我只提到它以防有人能想到我想不到的 mod_rewrite 解决方案。 - 最后两个位置的重复路径组件会导致它失败。例如,如果我请求
/home/home
或/some/path/path
我得到一个标准的 Apache 404 说最后两个路径组件未找到(在上面/home/home
的/path/path
两个示例中)。但是,如果我在末尾添加另一个路径组件,/home/home/something
那么它会再次起作用。我无法理解造成这种情况的原因。
任何人都可以解释为什么会发生这种情况,或者提出更好的方法来做到这一点?