我正在写一个简单的基于PHP的MVC框架。我希望这个框架能够安装在任何目录。
我的PHP脚本获取请求URI并将其分解为多个段,它将段1作为控制器,将段2作为操作,这样做就可以了:
http://www.example.com/mvc/module/test/
它将转到特定的模块控制器和方法。现在我有一个默认的控制器,家庭控制器,它在文件夹家庭。
现在,当我直接访问此文件夹http://www.example.com/mvc/home/
时,它将显示403 forbidden
,因为此文件夹确实存在,相反,它也应该返回到http://www.example.com/mvc/index.php
如果我将框架安装在一个不同的文件夹中,比如说文件夹framework,它必须重定向回http://www.example.com/framework/index.php
我想将每个文件夹和php文件重定向回index.php,让其他一切保持原样。
我遇到的第一个问题是它从来不会重定向到正确的文件夹,总是重定向到域根文件夹。
我是这么试的:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . index.php [L]
8条答案
按热度按时间2nbm6dog1#
您的重写规则看起来基本正常。
首先确保
.htaccess
文件在文档根目录中(与index.php
相同的位置),否则它只会影响它所在的子文件夹(以及其中的任何子文件夹-递归)。接下来,对规则进行细微更改,使其类似于:
目前,您只是在
.
上进行匹配,.
是任何字符的一个示例,您至少需要.*
来匹配任何字符的任何数量的示例。$_GET['path']
变量将包含伪目录结构,例如/mvc/module/test
,然后您可以在index.php中使用它来确定 Controller 和您想要执行的操作。如果你想把整个shebang安装在一个子目录中,比如
/mvc/
或/framework/
,最简单的方法是稍微修改重写规则来考虑这个问题。并确保您的
index.php
位于该文件夹中,而.htaccess
文件位于文档根目录中。$_GET['path']
的替代方案(于2018年2月和2019年1月更新)将 path 设置为
$_GET
变量实际上是没有必要的(现在甚至也不常见),许多框架将依赖$_SERVER['REQUEST_URI']
来检索相同的信息-通常是为了确定使用哪个 Controller-但原理完全相同。这确实稍微简化了
RewriteRule
,因为您不需要创建 path 参数(这意味着OP的原始RewriteRule
将工作):但是,有关在子目录中安装的规则仍然适用,例如
旗帜:
NC
= No Case(不区分大小写,由于模式中没有字符,因此实际上不需要)L
=最后一个(在此重写之后,它将停止重写,因此请确保它是重写列表中的最后一个)QSA
= Query String Append,以防你在末尾有类似?like=penguins
的东西,你想保留并传递给index.php。yv5phkfx2#
要将不存在的所有内容重定向到
index.php
,还可以使用**FallBackResource
**指令它的工作原理与
ErrorDocument
相同,当您请求服务器上不存在的路径或文件时,该指令会静默地将请求转发到index.php
。如果要将所有内容(
including existant files or folders
)重定向到index.php
,可以使用如下代码:注意,模式
^((?!index\.php).+)$
匹配除index.php
之外的任何uri,我们排除了目标路径以防止无限循环错误。0s7z1bwu3#
对于这个 * 问题 *,有一个"窍门"适合所有场景,一个如此明显的解决方案,你将不得不尝试它才能相信它实际上是有效的...:)
在这里...
基本上,您是在请求MOD_REWRITE将URI请求转发到
index.php
总是在文件存在时以及总是在请求的文件不存在时!在研究MOD-REWRITE的源代码以了解它的工作原理时,我意识到它的所有检查总是在验证引用的文件是否存在之后进行的。只有这样,
RegEx
才被处理。即使当你的URI指向一个文件夹,Apache也会强制检查其配置文件中列出的 * 索引文件 *。基于这个简单的发现,显而易见,只要我们双击文件存在检查并将两个结果路由到同一个端点,覆盖100%的可能性,一个简单的文件验证就足以所有可能的调用。
index.php
中没有"/**"。默认情况下,MOD_REWRITE将使用设置为"基本文件夹"的文件夹进行转发。其优点在于它不一定是站点的"根文件夹",因此此解决方案适用于localhost/
和/或您应用它的任何子文件夹。最后,我之前测试过的一些其他解决方案(看起来运行良好的那些)破坏了PHP通过相对路径"请求"文件的能力,这是一个令人沮丧的问题。
有些人可能会说这是一个不优雅的解决方案,实际上可能是这样,但就测试而言,在几个场景、几个服务器、几个不同的Apache版本等情况下,这个解决方案在所有情况下都100%有效!
bvk5enib4#
您可以使用类似于以下内容的内容:
这会将每个查询重定向到根目录的index.php。注意,它还会重定向对现有文件的查询,如图像、javascript文件或样式表。
zfycwa2u5#
愚蠢的答案,但如果你不知道为什么它不重定向检查,以下是为网络文件夹启用。
AllowOverride All
这将使您能够运行必须运行的htaccess!(有替代方案,但没有将导致问题https://httpd.apache.org/docs/2.4/mod/core.html#allowoverride)
wmomyfyw6#
如果目录存在(对于核心框架文件夹和文件),您可能还想知道如何将所有请求重定向到框架索引处理程序,在一些错误/成功尝试之后,我注意到我只需要更改.htaccess文件中的RewriteCond
上面的条件声明“未找到文件”和“未找到目录”,好吧,如果只是删除“未找到”(!-d)行,并以类似下面的内容结束呢:
它对我来说就像一种魔力
czfnxgou7#
我在Laravel 7项目中遇到了同样的问题,在Debian 10的共享主机中,我必须在/public/目录中添加
RewriteBase /
到我的.htaccess中,所以.htaccess看起来像n6lpvg4x8#
完成此操作后,不要忘记在
<a href="{the chosen redirected name}"> home</a>
中更改您的href
示例:
.htaccess
文件PHP文件: