我使用以下工具管理大量 PHP 应用程序前端控制器s 和以下 htaccess 文件:
FallbackResource /index.php
是的,这是整个文件(针对每个应用程序)!
但是,一些网站位于子文件夹中,因此需要进行以下更改:
FallbackResource /subfolder/index.php
你可能已经猜到了,/
开头的表示路径是相对于站点/虚拟主机的,而这里的路径需要相对于目录的。
(如果我使用mod_rewrite
而不是mod_dir
,我将必须RewriteBase
以类似的方式根据需要向每个子目录添加。)
我认为我可以通过以下方式解决这个问题:
FallbackResource index.php # No slash!
但是,当站点的重写包含斜杠时,例如,如果应用程序是,/store/
而其中的路径是products/1234
,那么 Apache 会查找/store/products/index.php
而不是,/store/index.php
并返回 500,并在日志中包含以下消息:
由于可能的配置错误,请求超出了 10 个子请求嵌套级别的限制。如有必要,请使用“LimitInternalRecursion”增加限制。使用“LogLevel debug”获取回溯。
我原以为该FallbackResource
路径是相对于配置它的 .htaccess 文件而言的,但看起来它实际上是相对于请求的 URL 而言的。
有没有办法可以按照FallbackResource
我预期的方式行事?
如果这是答案,我可以按原样使用它,但如果可以做到这一点,管理我拥有的网站将变得容易得多。这些网站使用相同的基本代码,但主题和数据库连接不同,现在的工作方式是每次部署新版本的代码时我都必须修改 htaccess 文件(因为它已签入 Git)。如果我们可以做到不必每次都记得进行此修改,那就太好了。
答案1
我认为这并非易事。我尝试在主配置文件中使用这两个指令中较新的变量插值来组合DirectoryMatch
和。LocationMatch
尽管类似这样的FallBackResource index.html
配置是完全有效的,但我与 Michael Hampton 一样担心,任何使用相对 URL 都可能导致问题。对于FallBackResource index.html
特定目录树,index.html 必须总是存在,否则您将获得针对index.html
无法找到的请求描述的递归循环。
就您而言,您需要一个带有的顶级.htaccess
文件FallBackResource /index.html
,然后FallBackResource /subfoldername/index.html
位于每个相关的子文件夹中。
生成这些内容的简单脚本可能是最安全的。
答案2
我最初提出该问题的网站已不再存在,但以下是我最终做的事情。
我最终将这些网站移至运行 Nginx 的服务器,其中所有配置均使用try_files
指令在服务器的配置文件中完成。这样管理起来容易得多。
答案3
DirectoryIndex
我相信使用而不是 的解决方法FallbackResource
也可能有效。以下内容将匹配/a/script/
文件/some/path/to/a/script/index.py
then /some/path/to/a/script/index.html
then/some/path/to/subfolder/index.py
和 finally /some/path/index.py
。这依赖于DirectoryIndex
遵守绝对路径。
ScriptAlias / "/some/path/to/"
<Directory "/some/path/to/">
Options +ExecCGI
AddHandler cgi-script .py
DirectoryIndex index.py index.html
# Appending /index.py seems to work whereas FallbackResource does not
DirectoryIndex /subfolder/index.py
DirectoryIndex /index.py
FallbackResource /index.py
Require all granted
</Directory>
重复调用将DirectoryIndex
附加到先前的调用。在我的情况下FallbackResource
不起作用,我偶然发现了一个解决方案。以上适用于 CGI/Python 文件,但我相信它在您的场景中也适用。
答案4
在旁边:使用 mod_rewrite 的解决方案
使用 mod_rewrite 您可以避免父目录的依赖(硬编码)。
(如果我使用
mod_rewrite
而不是mod_dir
,我将必须RewriteBase
以类似的方式根据需要向每个子目录添加。)
你会不是需要RewriteBase
在此处添加。事实上,您应该避免RewriteBase
在这种情况下添加指令。(不要复制常用的 WordPress 前端控制器模式。)然后使用相对的代换字符串(在RewriteRule
指令中)到前端控制器。相对代换字符串与包含文件的目录相关。因此,如果您准备使用 mod_rewrite,.htaccess
这当然是一种可以接受的解决方法,可以避免对父目录产生依赖。FallbackResource
而且如果您已经使用 mod_rewrite 进行其他重写,那么使用 mod_rewrite 作为前端控制器模式也可以说是首选解决方案。
mod_rewrite 解决方案与 mod_dir 结合使用DirectoryIndex
。对“根”目录本身的请求由 mod_dir 处理,而不是 mod_rewrite。(也就是说,应用程序的“根” - 子目录 - 不一定是 vHost 的“文档根”。)
例如,目录中的所有内容(包括index.php
和) :.htaccess
/subfolder
# /subfolder/.htaccess
DirectoryIndex index.php
RewriteEngine On
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php [L]
第一个RewriteRule
指令只是一种优化,并非绝对必要,以使它“工作”。此规则避免了在将请求重写为 后进行不必要的文件系统检查index.php
。或者,在 Apache 2.4 上,您可以使用 标志END
代替L
最后一条规则。
在没有指令的情况下RewriteBase
,最后一个RewriteRule
指令(使用相对的替换字符串)将请求重写为/subfolder/index.php
(文件所在的目录.htaccess
)。
即使在您确实需要知道父目录的名称的情况下,也可以再次使用 mod_rewrite 来计算。