我正在尝试做很多次以前做过很多次的事,但我似乎无法让这个工作。我已经尝试了将近2天了,我一直在网上搜索一个有效的例子,发现了许多非常相似的SO问题,但没有一个问题对我有用 - 大多数是按照关键/价值方法进行的,我只想要一系列价值观。
我想要的是什么:
我希望能够使用搜索引擎友好的网址。由于当前网站的工作方式的性质,我想转换此请求URI:
/this/is/a/random/path
...为:
/index.php?p[]=this&p[]=is&p[]=a&p[]=random&p[]=path
因此,当它到达PHP时,它将作为$_GET['p']
中的索引数组提供。我也希望它能够容忍一个尾随斜杠,所以我会得到相同的结果:
/this/is/a/random/path/
我是如何尝试的:
我对正则表达式并非太坏了,我对mod_rewrite的运作方式有一个合理的理解,但我认为我已经消失了,到目前为止,我已经无法再看到错误的道路了。
以下是我目前的情况:
# Turn mod_rewrite on RewriteEngine On # Allow direct loading of files in the /static directory RewriteCond %{REQUEST_FILENAME} -f RewriteRule ^/?static/(.+)$ - [L] # Recursively capture all path components RewriteCond %{REQUEST_URI} !^/?(?:index\.php)?$ RewriteRule ^/?([^/]+)(?:/(.+)$|/?$) $2?p[]=$1 [QSA,L] # Send request to controller RewriteRule ^.*$ index.php [QSA]
出了什么问题:
第一个RewriteCond
/ RewriteRule
对很好地工作 - 如果我请求/static
目录中存在的文件,请求保持原样并且文件被提供。如果该文件不存在,则会进入第二组规则,这样我就可以显示一个基于PHP的性感错误页面。
问题在于第二个RewriteCond
/ RewriteRule
对,可能还有第三个RewriteRule
。该条件应该在那里确保最后的迭代不会导致脚本名称被添加到数组 - 这似乎工作。以下是我认为第二个RewriteRule
正在做的事情,我怀疑我错过了一些显而易见的事情:
^/? # Start of string with optional leading slash ([^/]+) # Capture all characters up to next slash (?:/(.+)$|/?$) # Either grab all characters after the next slash or match the end $2?p[]=$1 # Push captured path component onto the array and shift URI down [QSA,L] # Merge previous query string, continue to next iteration
这是90%的工作。我遇到的问题:
array_reverse()
在PHP中很容易解决。我只提到它,以防任何人都能想到我不能的mod_rewrite解决方案。/home/home
或/some/path/path
,我会得到一个标准的Apache 404,说明找不到最后两个路径组件(上面两个示例中为/home/home
和/path/path
) 。 然而如果我将另一个路径组件添加到最后,例如/home/home/something
,那么它会再次起作用。我无法解决造成这种情况的原因。任何人都可以解释为什么会发生这种情况,或建议更好的方法来做到这一点吗?
答案 0 :(得分:1)
这不会更容易:
RewriteCond ${REQUEST_FILENAME} !-f
RewriteCond ${REQUEST_FILENAME} !-d
RewriteRule .* rewrite.php [L]
rewrite.php:
<?php
$p = array_filter(explode('/',parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)));
// you _could_ of course do an EVIL $_GET['p'] = $p, but I prefer to leave
// the superglobals 'read-only'. Not touching $_GET does however mean
// that index.php needs to be altered somewhat, allowing for a check on isset($p)
// and using that as input
include 'index.php';
?>
在apache中重写一切都很好,但通常只是解析&amp;确定PHP本身的动作要容易得多,以后也更容易维护/修改。
如果我通过路径请求它们,你的htaccess将允许直接访问文件,我不想这样做,除非它们在/ static
中,否则我不想这样做
此时不允许更多或更少的访问权限。只有你的index.php&amp; rewrite.php可以访问其他任何东西都可以在文档根目录之外,其中文件应该驻留在你不希望允许访问的位置。除非您使用此输入盲目地在index.php
中包含文件....我不会错过有关现有文件请求的部分,该文件也应该通过管道传送到index.php
。在这种情况下,这样的事情会做:
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^/?static/(.+)$ - [L]
RewriteCond ${REQUEST_URI} !^/?(index\.php)?$
RewriteRule .* rewrite.php [L,QSA]
顺便说一下,没有回调的array_filter()是什么?到目前为止,我可以看到所有它将做的是剥离空组件和0组件,我可能想要允许0。
这是为了防止像/foo//bar
这样的错误网址造成空洞的“鬼魂”(请注意双//
。
preg_split('#/ +#',$ str,-1,PREG_SPLIT_NO_EMPTY);更好吗?
如果你想允许0 /其他被array_filter
过滤的东西,那么是的,那个解决方案会更好。