如何使用 .htaccess 文件重写子目录的 URL?

Posted

技术标签:

【中文标题】如何使用 .htaccess 文件重写子目录的 URL?【英文标题】:How can I use the .htaccess file to rewrite URL's for a subdirectory? 【发布时间】:2021-03-14 11:29:49 【问题描述】:

我目前正在使用它来使我的网址看起来更漂亮:

ErrorDocument 403 /404.php
ErrorDocument 404 /404.php
Options -Indexes

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %REQUEST_FILENAME !-f
RewriteCond %REQUEST_FILENAME/index.html !-f
RewriteCond %REQUEST_FILENAME/index.php !-f
RewriteRule . index.php [L]
</IfModule>

我终于让它工作了(我对此很陌生),但现在我需要它来为位于主站点子目录中的“子站点”工作。而不是重写https://example.com/index.php,它需要重写https://example.com/sub/index.php

我尝试了一些方法,例如更改 RewriteBase 和 RewriteRule,但没有成功。

为了确定,我应该可以将另一个 .htaccess 放在子目录中,并期望它重写 example.com/sub 的 url,对吧?

提前致谢!

编辑 我向主 .htaccess 添加了例外,如下所示: 错误文档 403 /404.php 错误文档 404 /404.php 选项-索引

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %REQUEST_FILENAME !-f
RewriteCond %REQUEST_URI !^(/controle|/controle/|/voting|/voting/.*)$
RewriteCond %REQUEST_FILENAME/index.html !-f
RewriteCond %REQUEST_FILENAME/index.php !-f
RewriteRule . index.php [L]
</IfModule>

但是,我仍然不知道将什么放入子目录中的 .htaccess 中,同一个不起作用,我尝试更改类似的内容 RewriteBase /RewriteBase /subdir1/

【问题讨论】:

“为了确定,我应该可以将另一个 .htaccess 放在子目录中,并期望它重写 example.com/sub 的 url,对吧?” - 不,只要你的根级别 .htaccess 已经捕获了这些请求 - 那么它们就会被那个请求重写。因此,您需要为这些重写添加一个例外,即他们只留下 sub/ 声明的任何内容。 我会添加例外情况,谢谢!在将异常添加到根 .htaccess 文件后,您是否还知道我应该更改哪些内容以使此 .htaccess 对 sub/ 起作用? 当您添加异常时,几乎相同的东西也应该放在子文件夹中的 .htaccess 中。当然,您也可以直接在根级别添加它(如果您愿意) - 首先匹配以 sub/ 开头的任何请求路径,然后将其重写为 sub/index.php,然后为根级别执行这些操作。 请编辑您的问题并在其中添加格式正确的代码,以难以阅读的 cmets 格式。 @CBroe 默认情况下,/subdirectory/.htaccess 文件中的 mod_rewrite 指令将完全覆盖根 .htaccess 文件中的 mod_rewrite 指令。无需例外。 【参考方案1】:

为了确定,我应该可以将另一个.htaccess 放在子目录中,并期望它重写example.com/sub 的网址,对吧?

是的。默认情况下,/subdir/.htaccess 文件中的 mod_rewrite 指令将完全覆盖父/根 .htaccess 文件中的 mod_rewrite 指令。但是,您需要重新定义 ErrorDocument 指令才能覆盖根目录。

RewriteCond %REQUEST_FILENAME/index.html !-f
RewriteCond %REQUEST_FILENAME/index.php !-f

澄清一下,在这两个条件下,您是否希望偶尔从请求的子目录中提供index.htmlindex.php (DirectoryIndex) 文档,而不是将请求路由到文档根目录中的/index.php?在这种情况下,简单地检查请求是否映射到目录(即RewriteCond %REQUEST_FILENAME !-d)会更常见(并且稍微更优化)。除非有一些物理子目录要路由到文档根目录中的/index.php

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %REQUEST_FILENAME !-f
RewriteCond %REQUEST_FILENAME/index.html !-f
RewriteCond %REQUEST_FILENAME/index.php !-f
RewriteRule . index.php [L]
</IfModule>

这些指令可以稍微简化 - 如果您想将相同的指令应用于/subdir 中的子站点(并改为提供/subdir/index.php),这将有助于您。

完全删除RewriteBase 指令。相对 susbtitution 字符串,即。然后index.php 将相对于.htaccess 文件所在的目录(或继承)。

您也不需要&lt;IfModule mod_rewrite.c&gt; 包装器。有关此问题的更多信息,请参阅 my answer 到网站管理员堆栈上的以下问题:https://webmasters.stackexchange.com/questions/112600/is-checking-for-mod-write-really-necessary

所以,上面可以写成:

RewriteEngine On

RewriteCond %REQUEST_FILENAME !-f
RewriteCond %REQUEST_FILENAME/index.html !-f
RewriteCond %REQUEST_FILENAME/index.php !-f
RewriteRule . index.php [L]

(请注意我上面关于用目录检查替换这两个条件的评论。)

现在,您可以简单地将确切的 same 指令复制到 /subdir/.htaccess 文件中,这些指令现在会将请求路由到 /subdir/index.php,而不是覆盖父级中的 mod_rewrite 指令。

无需复制Options -Indexes,除非您想更改此选项。

或者,如果您想应用完全相同的指令(但与/subdir 相关),您可以简单地在/subdir/.htaccess 文件中启用 mod_rewrite 继承。例如:

# /subdir/.htaccess

ErrorDocument 403 /subdir/404.php
ErrorDocument 404 /subdir/404.php

RewriteEngine On
RewriteOptions Inherit

RewriteOptions Inherit 的作用本质上是从父配置中“复制” mod_rewrite 指令,即。 /.htaccess 位于根目录中,位于当前 /subdir/.htaccess 文件中的指令后面。重要的是要澄清指令是“复制的”,它们不像在根 /.htaccess 文件中那样就地运行。

【讨论】:

以上是关于如何使用 .htaccess 文件重写子目录的 URL?的主要内容,如果未能解决你的问题,请参考以下文章

.htaccess 从子目录重写到根目录

htaccess - 重写具有同名目录的文件

重写 .htaccess 中子目录的 url

.htaccess Rewrite apache重写和配置

使用 .htaccess 将变量重写到目录

从 HTACCESS 文件中的所有 ISAPI 重写 3 规则中排除目录