从父目录为index.php提供服务的htaccess重写规则
我正在寻找将映射以下内容的.htaccess重写规则从父目录为index.php提供服务的htaccess重写规则,php,apache,.htaccess,mod-rewrite,url-rewriting,Php,Apache,.htaccess,Mod Rewrite,Url Rewriting,我正在寻找将映射以下内容的.htaccess重写规则 GET /a/ => a/index.php GET /a/b/ => a/b/index.php GET /a/b/c/ => a/b/index.php 基本上,如果某个目录中存在index.php文件,则应该提供该文件。如果没有,那么它应该在父目录中查找index.php并提供服务 我试图在PHP中获得干净的URL,而不必通过单个index.PHP文件路由所有内容。.htaccess Rewr
GET /a/ => a/index.php
GET /a/b/ => a/b/index.php
GET /a/b/c/ => a/b/index.php
基本上,如果某个目录中存在index.php文件,则应该提供该文件。如果没有,那么它应该在父目录中查找index.php并提供服务
我试图在PHP中获得干净的URL,而不必通过单个index.PHP文件路由所有内容。.htaccess
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) ./index.php?__path__=$1&%{QUERY_STRING}
index.php
$path = '';
if (is_array($_GET) && array_key_exists('__path__', $_GET)) {
$path = trim($_GET['__path__']);
}
$path = trim($path, '/');
//you can use $path, path can be "a", "a/b" or "a/b/c" for your samples
第一种解决方案假设请求映射到一个物理目录路径,例如,
/a/b/c/
格式的请求中的a
、b
和c
都是文件系统上的目录
您不需要为此使用mod_rewrite(即RewriteRule
)。您可以只指定相对DirectoryIndex
文档。例如,要处理4层深的目录结构(即/a/b/c/
):
如果没有找到目录索引文档,那么您将得到通常的403禁止(假设目录索引被禁用)
如果沿着文件系统路径删除了所有index.php
文档,那么如果它试图获取文档根上的索引文档,则会收到400个错误请求
更新:然而,似乎真正需要的是一个多级前端控制器类型模式,因为请求的URL不一定作为物理文件系统路径存在。例如,给定一个形式为
/a/b/c/
的URL,那么可能只有a
和b
是物理目录,c/
只是一个额外的URL路径,应该传递给位于/a/b/index.php
或/a/index.php
甚至/index.php
的前端控制器,取决于先找到哪个
对于通用的任意目录级深度目录结构,可以执行以下操作:
RewriteEngine On
# Exception - Reached the document root then stop
# (Prevents rewrite loop if index.php is missing - 404 instead)
RewriteRule ^index\.php$ - [L]
# Exception - Any request for a valid file stop here
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
# If already requesting "index.php" then step up a directory
RewriteRule ^(.*/)?[^/]+/index\.php$ /$1index.php [L]
# Otherwise try "index.php" in the current path segment
RewriteRule ^(.*/)?[^/]*$ /$1index.php [L]
正则表达式开头的可选(.*/)?
模式允许钻取到文档根。如果这不是可选的(并且在捕获的模式中包含斜杠),那么它将停止文档根目录下的一个目录(即位于/a/index.php
)
通过不特别检查请求是否映射到一个目录,当请求的目录中缺少前端控制器时,它可以调用父目录中的前端控制器。经过一些修补,我找到了一个似乎有效的解决方案。我基本上是捕获已知的路径段,并使用捕获变量相对于文档根映射到文件系统。然而,最好有一个深入N层的正则表达式,它需要多个重写规则
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
# 3 levels deep
# GET /a/b/c-some-thing-here
RewriteRule (.*)/(.*)/(.*) /$1/$2/index.php [L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
# 4 levels deep
# GET /a/b/c/d-some-thing-here
RewriteRule (.*)/(.*)/(.*)/(.*) /$1/$2/$3/index.php [L]
默认情况下,与PHP开发服务器的路由也是这样工作的。这是什么“PHP开发服务器”?这种方法的问题在于,您可能会创建重复的内容(为相同内容提供多个URL)。。。e、 例如,从命令行运行
php-S localhost:5000
,我不担心有重复的内容。在我的例子中,index.php将最后一个“目录”视为脚本的参数。。问题中的示例中的“c”仍然通过PHP文件路由所有内容。我想跳过任何PHP逻辑并将所有内容强制放到index.PHP文件中。好吧,我误解了:(您可以使用angular style hashtags domain.com/#!这对我不起作用。它只是404s。还有什么需要启用的吗?DirectoryIndex
是mod_dir的一部分,默认情况下启用。不需要任何其他内容。您可能需要先重置DirectoryIndex
(尽管不太可能)您的.htaccess
文件中是否有其他指令?是否有其他.htaccess
文件?My.htaccess位于文档根目录中,子文件夹中没有其他.htaccess文件。在.htaccess文件中唯一的内容是您发布的一行代码段。啊,那么,您真的是在追求多前端控制器类型的模式,其中URL路径可以映射到真实的目录路径,也可以完全是虚拟的?我必须对此进行另一种思考。效果很好。谢谢!我已经包含了此模式的更通用(N级深度)版本。
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
# 3 levels deep
# GET /a/b/c-some-thing-here
RewriteRule (.*)/(.*)/(.*) /$1/$2/index.php [L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
# 4 levels deep
# GET /a/b/c/d-some-thing-here
RewriteRule (.*)/(.*)/(.*)/(.*) /$1/$2/$3/index.php [L]