.htaccess: ??/index.php --> ??/,建立在相对路径上

.htaccess: ??/index.php --> ??/, built on a relative path

从 URL 中删除 indx.php;始终从 ??/index.php

重定向 ??/

...包括子目录,可能有自己的 .htaccess 和 index.php.

我正在使用带 .htaccess 的 Apache。

我在域的子目录中有一个带有 index.php 的网络应用程序,在这里说:

example.tld/somedir/

但是,它可以安装到任何目录,例如这些...

example.tld/anotherdir/
sub.domain.tld/
another.tld/

始终通过 .htaccess

隐藏 index.php

我想确定:

  1. 所有以上四个 /(根)地址 link 到 index.php 在任何同一目录中。
  2. index.php 总是重定向到 / (root)
  3. 例子
example.tld/anotherdir/index.php   -> example.tld/anotherdir/
sub.domain.tld/index.php           -> sub.domain.tld/
another.tld/index.php              -> another.tld/

我需要这样的东西

RewriteRule ^.*$ /{$PWD}/index.php [L,QSA]

...以及任何必须在它之前的重写语句。


这些问题提供答案:

要从请求的目录提供 index.php,您可以使用 mod_dir 的 DirectoryIndex 指令(可能已经在服务器配置中设置,尽管默认为 index.html仅) - 你不需要 mod_rewrite 。例如:

# Serve "index.php" from the requested directory
DirectoryIndex index.php

这指示 Apache 从请求的任何目录提供服务 index.php。例如。请求 /foo/bar/ 然后 /foo/bar/index.php 通过内部子请求(无重定向)提供服务。如果 index.php 不在该目录中,您将收到 403 Forbidden 响应(假设目录列表 - 由 mod_autoindex 生成 - 被禁用)。

要从直接请求的任何 URL 中 删除 index.php,您可以使用 mod_rewrite。例如:

RewriteEngine On

# Remove "index.php" from any URL and redirect back to the "directory"
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.+/)?index\.php(/|$) / [R=301,L]

以上将重定向如下,保留请求的协议和主机名:

  • /index.php/
  • /foo/index.php/foo/
  • /foo/bar/index.php/foo/bar/
  • /fooindex.php - 无重定向(预期 404)
  • /foo/index.php/bar(包含 path-info)到 /foo/(删除了 path-info)
  • /foo/index.phpbar - 无重定向(预计 404)

(可选)捕获组 (.*/)? 包含 index.php 之前的 URL-path 部分。然后可以使用 </code> 反向引用在 <em>substitution</em> 字符串中使用。在文档根目录中请求 <code>/index.php 的情况下,这是 empty。当存在子目录时,它包含 subdir/ 形式的字符串,包括尾部斜杠。

如果您的 .htaccess 文件中没有其他指令,那么您并不严格需要检查 REDIRECT_STATUS 环境变量的 条件 。此 条件 确保只有直接请求被重定向,以防您在文件中稍后有 front-controller 模式可能将请求重写为 index.php.

如果文件中确实有其他指令,那么顺序可能很重要。通过外部重定向删除 index.php 的规则必须位于 之前 任何现有重写,靠近文件顶部。

请注意,这会从 URL 中删除 index.php,而不管请求的 URL 是否实际映射到真实文件,或者前面的 URL-path 是否作为一个文件存在物理目录。因此,无论 /<something>/ 是否为物理目录,/<something>/index.php 都会重定向到 /<something>/。此检查可以以额外的文件系统检查为代价来实现 - 但它可能不是必需的。

注意:首先使用 302(临时)重定向进行测试,以避免潜在的缓存问题。只有在您测试它按预期工作后才更改为 301(永久)重定向。


更新#1:

These Questions do not provide an answer:

  • htaccess redirect index.php to root (including subdomains)

    • This does not address subdirectories, only subdomains
    • This redirects example.tld/dir/index.php to example.tld/, but I need example.tld/dir/

实际上,您链接到 的第一个问题确实 回答了您的问题,关于从请求的 URL 中删除 index.php。它 确实 寻址子目录并将 example.tld/dir/index.php 重定向到 example.tld/dir/(不是你所说的 example.tld/)。

问题中讨论子域的部分有点误导,因为它实际上与具体的子域没有任何关系。

链接问题中提供的解决方案基本上与我在上面所做的相同,除了它可以说匹配太多(而且不够)。它会 incorrectly/unnecessarily 将 /fooindex.php 重定向到 /foo(没有尾部斜杠)并且无法重定向包含 path-info 的 URL(这可能是恶意的)。例如。 /foo/index.php/bar 将无法重定向,但仍会提供 /foo/index.php 的内容(除非 AcceptPathInfo 已被禁用)。尽管这些“错误”是否真的会导致您的情况出现问题是另一回事。


更新#2:

I have the code exactly in the directory for example.tld/dir

上面的代码假定 .htaccess 文件位于文档根目录中。如果 .htaccess 文件位于应用程序的安装目录中,那么您需要像这样修改上面的内容:

# Remove "index.php" from any URL and redirect back to the "directory"
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{REQUEST_URI} ^/(.+/)?index\.php
RewriteRule (^|/)index\.php(/|$) /%1 [R=301,L]

%1 反向引用(与 </code> 相反)指的是前面 <em>CondPattern</em> 中捕获的组。这自然包括完整的 URL-path,因此避免了必须对 <code>.htaccess 文件所在的目录进行硬编码。

这适用于包含 .htaccess 文件及其所有子目录的目录。请注意,默认情况下,这会完全覆盖父 .htaccess 文件中可能存在的任何 mod_rewrite 指令(默认情况下不继承 mod_rewrite 指令)。

...including subdirectories, which may have their own .htaccess and index.php.

如果其他 sub-subdirectories 有自己的 .htaccess 文件,那么这可能会或可能不会工作,具体取决于这些 sub-subdirectory .htaccess 文件中使用的指令 and/or 如何mod_rewrite继承配置。

mod_rewrite 指令默认不继承。因此,如果 sub-subdirectory 中的 .htaccess 文件启用了重写引擎,那么父目录中的上述 mod_rewrite 指令将被完全覆盖(它们甚至没有被处理)。

另一方面,如果 sub-subdirectory 中的 .htaccess 文件使用其他模块的指令,那么这可能不是一个 i起诉。