这很棘手,但这是一个递归遍历给定 REQUEST_URI 的父目录的代码,它支持无限深度。
通过httpd.conf启用mod_rewrite和.htaccess,然后把这段代码放到你.htaccess的DOCUMENT_ROOT目录下:
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /
# If the request is for a valid file
RewriteCond %{REQUEST_FILENAME} -f [OR]
# If the request is for a valid link
RewriteCond %{REQUEST_FILENAME} -l
# don't do anything
RewriteRule ^ - [L]
# if current ${REQUEST_URI}.php is not a file then
# forward to the parent directory of current REQUEST_URI
RewriteCond %{DOCUMENT_ROOT}/$1/$2.php !-f
RewriteRule ^(.*?)/([^/]+)/?$ $1/ [L]
# if current ${REQUEST_URI}.php is a valid file then
# load it be removing optional trailing slash
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^(.*?)/?$ $1.php [L]
说明:
假设原始 URI 是:/index/foo/bar/baz。另外假设%{DOCUMENT_ROOT}/index.php 存在,但DOCUMENT_ROOT 下不存在其他php 文件。
RewriteRule #1 有一个正则表达式,它将当前的 REQUEST_URI 分成两部分:
- 除了
$1 的最低子目录之外的所有子目录,这里将是index/foo/bar
-
$2 的最低子目录,此处为baz
RewriteCond 检查%{DOCUMENT_ROOT}/$1/$2.php(转换为%{DOCUMENT_ROOT}/index/foo/bar/baz.php)是否不是有效文件。
如果条件成功,则在内部重定向到$1/,此处为index/foo/bar/。
RewriteRule #1 的逻辑再次重复以使 REQUEST_URI 为(在每次递归之后):
index/foo/bar/
index/foo/
index/
此时,规则 #1 的 RewriteCond 失败,因为那里存在 ${DOCUMENT_ROOT}/index.php。
如果 %{DOCUMENT_ROOT}/$1.php 是一个有效文件,我的 RewriteRule #2 会转发到 $1.php。请注意,RewriteRule #2 具有匹配除最后一个斜杠之外的所有内容的正则表达式,并将其放入$1。这意味着检查%{DOCUMENT_ROOT}/index.php 是否为有效文件(确实如此)。
此时 mod_rewrite 处理已完成,因为此后两个 RewriteCond 都失败了,因此无法触发进一步的规则,因此 %{DOCUMENT_ROOT}/index.php 将由您的 Apache Web 服务器适当地提供服务。