使用 htaccess 将 all 重定向到 index.php

我正在编写一个简单的基于 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

如果我将框架安装在一个不同的文件夹,让我们说文件夹框架,它必须重定向回 http://www.example.com/framework/index.php

我想将每个文件夹和 php 文件重定向回 index.php,其他的都保持原样。

我遇到的第一个问题是它从来没有重定向到正确的文件夹,总是到域根文件夹。

这就是我试过的:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . index.php [L]
409390 次浏览

你可以使用这样的东西:

RewriteEngine on
RewriteRule ^.+$ /index.php [L]

这将把每个查询重定向到根目录的 index.php。注意,它还会重定向对现有文件的查询,如图像、 javascript 文件或样式表。

您的重写规则看起来几乎没问题。

首先确保您的 .htaccess文件在您的文档根目录中(与 index.php相同的位置) ,否则它只会影响它所在的子文件夹(以及该文件夹中的任何子文件夹——递归)。

接下来稍微修改一下你的规则,让它看起来像这样:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?path=$1 [NC,L,QSA]

现在你只需要在 .上匹配任何字符的 实例,你至少需要 .*来匹配任何字符的任何数量。

$_GET['path']变量将包含假的目录结构,例如 /mvc/module/test,然后可以在 index.php 中使用它来确定要执行的 控制员和操作。


如果您希望将整个 Shebang 安装在一个子目录中,比如 /mvc//framework/,最简单的方法是稍微改变一下重写规则,以考虑到这一点。

RewriteRule ^(.*)$ /mvc/index.php?path=$1 [NC,L,QSA]

并确保您的 index.php在该文件夹中,而 .htaccess文件在文档根目录中。


替代 $_GET['path'] (更新于2月18日和1月19日)

路径设置为 $_GET变量实际上是不必要的(现在甚至不常见) ,许多框架将依赖于 $_SERVER['REQUEST_URI']来检索相同的信息——通常是确定使用哪个 控制员——但原理是完全相同的。

这确实略微简化了 RewriteRule,因为您不需要创建 路径参数(这意味着 OP 的原始 RewriteRule 威尔现在可以工作了) :

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ /index.php [L,QSA]

但是 ,在子目录中安装的规则仍然适用,例如。

RewriteRule ^.*$ /mvc/index.php [L,QSA]



旗帜:

NC = No Case (不区分大小写,因为模式中没有字符,所以没有必要)

L = 最后一次(在这次重写之后它将停止重写,所以确保它是你重写列表中的最后一次)

QSA = Query String Append,以防最后出现类似于 ?like=penguins的内容,需要保留并传递给 index.php。

要将不存在的所有内容重定向到 index.php,还可以使用 FallBackResource指令

FallbackResource /index.php

它的工作原理与 ErrorDocument相同,当您请求服务器上不存在的路径或文件时,指令会悄悄地将请求转发给 index.php

如果您想将所有内容(including existant files or folders)重定向到 index.php,您可以使用如下代码:

RewriteEngine on


RewriteRule ^((?!index\.php).+)$ /index.php [L]

注意,模式 ^((?!index\.php).+)$匹配除 index.php之外的任何 uri,我们已经排除了目标路径,以防止无限循环错误。

愚蠢的回答,但如果你不能找出为什么它没有重定向检查以下是为网络文件夹启用。.

AllowOverride All

这将使您能够运行 htaccess 必须运行!(有替代品,但没有上会造成问题 https://httpd.apache.org/docs/2.4/mod/core.html#allowoverride)

这个 问题有一个适用于所有场景的“诀窍”,一个如此明显的解决方案,以至于你将不得不尝试去相信它实际上是有效的... :)

在这里..。

<IfModule mod_rewrite.c>


RewriteEngine On


RewriteCond %{REQUEST_FILENAME}  -f [OR]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [L,QSA]


</IfModule>

基本上,您要求 MOD _ REWRITE (重写)转发到 index.php的 URI 请求 总是在文件存在的时候总是当请求的文件不存在时

在研究 改写的源代码以了解它是如何工作的时候,我意识到如果引用的文件存在或者不存在,所有的检查都会在验证之后发生。只有这样才能处理 RegEx。即使您的 URI 指向一个文件夹,Apache 也会强制检查其配置文件中列出的 索引文件

基于这个简单的发现,很明显一个简单的文件验证对于 所有可能的电话来说就足够了,只要我们双击文件存在检查并将两个结果路由到同一个端点,覆盖100% 的可能性。

重要提示: 注意,index.php中没有“ /”。默认情况下,MOD _ REWRITE (重写)将使用被设置为“基本文件夹”的文件夹进行转发。它的美妙之处在于它不一定是站点的“根文件夹”,允许该解决方案适用于 localhost/和/或应用它的任何子文件夹。

最终,我之前测试过的一些其他解决方案(那些看起来运行良好的解决方案)破坏了 PHP 通过相对路径“需要”文件的能力,这令人沮丧。小心点。

有些人可能会说这是一个不雅的解决方案。实际上,它可能是,但就测试而言,在几个场景、几个服务器、几个不同的 Apache 版本等等中,这个解决方案在所有情况下都100% 有效!

这样做之后,不要忘记改变你的 href, <a href="{the chosen redirected name}"> home</a>

例如:

.htaccess文件

RewriteEngine On


RewriteRule ^about/$ /about.php

PHP 文件:

<a href="about/"> about</a>

如果你仍然想知道如何重定向所有请求,如果目录存在(对于核心框架文件夹和文件)到框架索引处理程序,在一些错误/成功尝试之后,我刚刚注意到我只需要在。Htaccess 文件

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

上面的条件声明“未找到文件”和“未找到目录”,好吧,如果只是删除“未找到”(!D)行,并以下面的内容结束:

RewriteEngine on
RewriteBase /framework/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /framework/index.php [L,QSA]

它对我来说就像魔法一样有效

我只是不得不面对与我的 Laravel7项目,在 Debian10共享托管相同的问题。我必须把 RewriteBase /加到我的。/public/目录中的 htaccess。所以。Htaccess 看起来像

RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ /index.php [L,QSA]