如何以编程方式确定 PHP 中的文档根目录?

Posted

技术标签:

【中文标题】如何以编程方式确定 PHP 中的文档根目录?【英文标题】:How to programmatically determine the document root in PHP? 【发布时间】:2010-09-28 06:20:15 【问题描述】:

这是我最近遇到的一个问题 - 网络主机上的 apache 配置错误。这意味着所有依赖$_SERVER['DOCUMENT_ROOT'] 的脚本都会中断。我发现的最简单的解决方法是在一些共享的全局包含文件中设置变量,但不要忘记它会很痛苦。我的问题是,如何以编程方式确定正确的文档根目录?

例如,在一台主机上,设置如下:

$_SERVER['DOCUMENT_ROOT'] == '/htdocs'

真正的文档根是:

test.example.com -> /data/htdocs/example.com/test
www.example.com -> /data/htdocs/example.com/www

我想要一个从www.example.com/blog/(在路径/data/htdocs/example.com/www/blog)运行的脚本,以获得/data/htdocs/example.com/www 的正确值。

在另一台主机上,设置有点不同:

$_SERVER['DOCUMENT_ROOT'] == '/srv'
test.example.com -> /home/virtual_web/example.com/public_html/test
www.example.com -> /home/virtual_web/example.com/public_html/www

有什么解决办法吗?或者是根本不依赖$_SERVER['DOCUMENT_ROOT'] 并修复我在我的网站上运行的所有软件的唯一方法?在主机端解决这个问题似乎不是一个选择,我还没有遇到一个配置正确的主机。我得到的最好的结果是一个指向 www.example.com 的文档根,它至少在 open_basedir 内部——他们使用了另一种命名方案,www.example.com 将指向/u2/www/example_com/data/www/

【问题讨论】:

【参考方案1】:

基于http://www.helicron.net/php/:

$localpath=getenv("SCRIPT_NAME");
$absolutepath=getenv("SCRIPT_FILENAME");
$_SERVER['DOCUMENT_ROOT']=substr($absolutepath,0,strpos($absolutepath,$localpath));     

我不得不更改 basename/realpath 技巧,因为它在我的主机上返回了一个空字符串。相反,我使用SCRIPT_FILENAME。这可能不再适用于 IIS(但使用 $_SERVER 变量的原始脚本可能也不会)。

【讨论】:

【参考方案2】:

这就是人们使用 htaccess 和/或查询字符串通过引导程序 /index.php 吸取所有内容的原因之一。您可以使用上面提到的dirname( __FILE__ ) 技巧并通过这种方式获得您应用的公共基础。

如果您过于深入而无法切换到单个入口点,我见过人们做的一件事是在他们的脚本中使用一个公共头文件,该头文件会沿着目录树向上查找一个对基本目录:

function findAppBase( $dir ) 
    if( file_exists( "$dir/unique_file.txt" ) ) 
        return $dir;

    return findAppBase( dirname( $dir ) );


$base = findAppBase( dirname( __FILE__ ) );

该代码尚未经过测试,使用 $_ENV$_SERVER 中的 var 可能会有更巧妙的方法,可以满足您的需求...

【讨论】:

谢天谢地,这不是问题,我只有一个入口点。只是我在多个域和主机上运行相同的软件,我必须为每个域修复它。我宁愿在上游提交一个修复程序,这样我就不必再关心它了。【参考方案3】:

为什么不要求您的虚拟主机正确配置他的服务器?

这类事情往往会默默地留在您的代码中,并且在有人最终修复服务器之前永远不会被删除(但仍然处于活动状态)。然后一切都会再次破裂。

或者,将您的东西移到可以工作的主机上。如果这被打破了,谁知道你接下来会发现什么。

【讨论】:

我不确定是否可以正确配置主机,这似乎是mod_vhost_alias的问题(根据webmasterworld.com/apache/3640691.htm的评论)。【参考方案4】:

无需修改所有脚本。

您可以使用auto_prepend_file 在运行任何脚本之前运行 PHP 文件。

$_SERVER 只是一个数组,您可以修改它并设置正确的$_SERVER['DOCUMENT_ROOT']

【讨论】:

在每次运行时都运行该脚本有点没用。 every 运行时运行该脚本有点没用。最好用一些 .htaccess 来处理它,而不是设置它。 您可以使用 .htaccess 中的 php_value 来设置 auto_prepend_file,但问题的作者提到了我认为不支持此功能的 IIS 服务器。 其实我并不关心IIS,只是最初的解决方案应该是“平台无关的”,我不确定它之后是否仍然有效。但是那个自动前置看起来很有趣,谢谢你的提示!【参考方案5】:

在 PHP5 中有一个神奇的常量__FILE__,它包含了它所在文件的绝对路径。您可以将它与 dirname 结合使用来计算文档根目录。

您可以在配置文件中添加如下语句

define ('DOCUMENT_ROOT', dirname(__FILE__));

这应该可以解决问题

【讨论】:

诀窍是使用文件的绝对名称(来自魔术常量或来自服务器变量)并将其与来自 SCRIPT_NAME 的文档根目录的绝对路径知识相结合。 从 PHP 5.3 开始,这也是 __DIR__ 使用它而不是 dirname(__FILE__) 但这只是返回当前文件的文件夹,不一定是网络服务器的实际根文件夹。 是的@Chuck,你是对的,但是,如果你不能依赖 $server 配置(如果不是真的强制,我不会依赖它的所有值)并且没有 const in你不得不求助于解决方法的地方。我建议的目的是解决这个非常具体的案例,更好地为解决方案提供提示。【参考方案6】:

PHP 应该将当前目录设置为脚本所在的目录,因此只要没有损坏,您应该能够使用 $_SERVER['SCRIPT_FILENAME']getcwd() 找出文档根目录. (我不记得所有的 $_SERVER 变量了,phpinfo() 中可能有一些更有用的东西。)

【讨论】:

我安装的一些脚本“太聪明了”并且知道它们安装在哪个目录(相对于理论文档根目录),并将其附加到文档根目录(在他们从数据库)。我仍然需要修改每个目录的代码以剥离目录......还是不?

以上是关于如何以编程方式确定 PHP 中的文档根目录?的主要内容,如果未能解决你的问题,请参考以下文章

如何以编程方式重命名 AWS Glue 目录中的列名

在文档目录中找不到 plist 文件?如何以编程方式修改 plist?

如何以编程方式将音乐从 pc 同步到 iphone 音乐库? [关闭]

如何以编程方式填充现有的 PDF 文档 [关闭]

以编程方式下载 Azure 文件共享文档

以编程方式确定最大文件名长度