获取PHP项目的根目录路径

160

我在PHP项目中有这样的文件夹结构。(如Eclipse所示)

-MySystem
    +Code
    +Data_Access
    -Public_HTML
        +css
        +js
        +Templates
    -resources

当我尝试这段代码时

echo $_SERVER['DOCUMENT_ROOT']

输出结果为

D:/workspace

如何获取系统(MySystem)的根目录路径,而不是硬编码文件夹名称?

14个回答

166

对于 PHP >= 5.3.0 版本,尝试使用 魔术常量

__DIR__

并将您的路径设为相对路径。

对于 PHP < 5.3.0 版本,请尝试

dirname(__FILE__)

3
太棒了!我尝试了 $_SERVER['DOCUMENT_ROOT']、dirname()、$_SERVER['SCRIPT_NAME'] 等等,但这个方法非常出色! - webblover
125
使用 __DIR__ 的结果取决于它的使用位置。它是相对于文件本身的,所以如果在一个子目录的 include 文件中使用它,它将不会返回你的根目录。 - Iris
35
不会给予根目录。 - inrsaurabh
12
如果有人偶然遇到这篇答案并寻找所问问题的答案,简单说明一下:__DIR__获取的是当前文件的目录而不是项目根目录,除非你在项目根目录中调用它。但由于PHP没有项目概念,所有路径都必须是绝对路径或相对于当前位置的路径。 - MikeT
8
请不要因为一个回答对你有帮助就点赞,如果它没有正确回答问题的话。 - ElYeante
显示剩余2条评论

104

当你说

$_SERVER['DOCUMENT_ROOT']

包含此路径:

D:/workspace

那么您需要的是 D:,对吗? 如果是这种情况,您可以通过斜线分割字符串并返回第一个:

$pathInPieces = explode('/', $_SERVER['DOCUMENT_ROOT']);
echo $pathInPieces[0];
这将输出服务器的根目录。
更新:当您使用常量 DIRECTORY_SEPARATOR 而不是硬编码斜杠('/')时,此代码在Windows下也可以运行。
更新2:全局变量 $_SERVER 并非始终可用。例如在命令行(cli)中。因此,您应该使用 __DIR__ 替代 $_SERVER['DOCUMENT_ROOT']__DIR__ 返回php文件本身的路径。

3
你可以使用 __DIR__ 代替 $_SERVER['DOCUMENT_ROOT'] - Armin
抱歉,如果我没有很好地解释我的问题,实际上我需要的是“D:/workspace/MySystem”。 - Nalaka526
1
如果您的根目录路径形式为"/var/public/www",那么使用此方法数组中的第一个字符串将为空(0)/(1)/(2)/(3)。根目录将是第二个字符串$pathInPieces[1]。 - tbradley22

36

使用 PHP 函数:

getcwd()

获取当前工作目录。


13
这会返回当前执行文件的路径,而不是根路径。 - Yousha Aleayoub

14

我想指向WordPress处理此事的方式:

define( 'ABSPATH', dirname( __FILE__ ) . '/' );

WordPress在Web上被广泛使用,也可以在本地运行良好,因此我非常信任这种方法。您可以在wordpress的wp-config.php文件底部找到此定义。


1
我猜这只在你有两个目录层级的时候才有效。是吗?我的意思是,当你从base_project_directory/folder1/folder2/folder3/file.php调用它时,它不会返回base_project_directory。 - Ali Khalili
由于WordPress在整个网络上被广泛使用并且在本地也运行良好,因此我对这种方法非常信任。但考虑到WordPress的代码质量和安全记录,我不认为这是一个特别好的论点。 - Alex Barker
2
@AlexBarker,我不同意你暗示WP有糟糕的安全记录。实际上,它非常安全,并且有一个专注于安全的响应团队 - 在最近几年中,核心部分几乎没有被利用的安全问题(包括你评论时的时间)。 - William Patton
1
实际上这并不起作用。没有进行太多调查,但看起来双重的 dirname 实际上会剥离一个目录(可能不是那些来到这个线程的人想要的 -> 例如我)。 - 43matthew
@43matthew 你说得对。过去它是这样工作的,但显然现在不再是这样了。由于WP也改变了定义,我相应地更新了我的答案。感谢你指出这一点。 - Hexodus

11

目前,PHP本身并没有提供一种确定获取项目根目录的方法。

但是您可以自己实现一个非常简单的方法,以确切地实现您想要的功能。

解决方案

在您的项目中创建一个新文件,比如说D:/workspace/MySystem/Code/FilesManager.php(使用任何名称和路径都可以),然后使用以下代码:

<?php

class FilesManager
{
  public static function rootDirectory()
  {
    // Change the second parameter to suit your needs
    return dirname(__FILE__, 2);
  }
}

现在你可以在这样的路径中执行此操作,比如说:D:/workspace/MySystem/Code/a/b/c/Feature.php

echo FilesManager::rootDirectory();

期望的结果应该是:

"D:/workspace/MySystem"

无论在项目中的哪个位置,输出将是相同的。

解释

使用dirname返回第一个参数的父目录。我们使用幻数常量 __FILE__ 来给出FilesManager.php文件的路径。第二个参数告诉我们在层次结构中向上移动的次数。在这种情况下,我们需要上移两次,但这实际取决于您将文件放在层次结构的什么位置。如果您只需要上移一次(即文件位于根目录中),则可以省略第二个参数。但是,此时可以直接返回__DIR__

这种解决方案保证可以工作,无论根目录在服务器上的何处。除非您最终将实用类移到其他位置。

补充说明

我建议避免使用DOCUMENT_ROOT,理由如下(根据这个答案):

  • 它使您的应用程序依赖于服务器。
  • Apache设置可能会给根目录提供不正确的路径。


1
dirname 的第二个参数帮了很大的忙。 - amir22
我尝试了你的解决方案,在本地主机上可以运行,但是当我在我的主机上使用它时,URL中会添加额外的“/”。 - Mahmoud Magdy

5
dirname(__FILE__)

这是一个有用的函数,但它只会获取相对于当前文件URL的当前路径,如果您在其他远离根目录的目录中(例如,includes目录),并且您需要从根目录获取文件夹,则可以使用整数参数2来向上走1级,以此类推。

echo dirname(__FILE__, 2);

之前

C:\laragon\www\x\includes\reports\charts

之后

C:\laragon\www\x\reports\charts

“reports”是在根目录x中的文件夹。


3
您可以尝试一下: $_SERVER['PATH_TRANSLATED'] 引用:
文件系统(而不是文档根目录)的路径,指向服务器完成任何虚拟到真实映射后的当前脚本。请注意:从 PHP 4.3.2 开始,在 Apache 2 SAPI 中 PATH_TRANSLATED 不再隐式设置,这与 Apache 1 的情况不同(当它未被 Apache 填充时,设置为与 SCRIPT_FILENAME 服务器变量相同的值)。
此更改是为了遵守 CGI 规范,即 PATH_TRANSLATED 只存在于 PATH_INFO 被定义的情况下。Apache 2 用户可以在 httpd.conf 文件中使用 AcceptPathInfo = On 来定义 PATH_INFO。
来源: php.net/manual

3
你还可以使用 realpath 方法。 realpath(".") 返回你的文档根目录。
你可以使用指定的路径调用 realpath。请注意,如果目标文件夹或文件不存在,它将无法正常工作。在这种情况下,它将返回 false,这对于测试文件是否存在可能是有用的。
在我的情况下,我需要为要写入磁盘的新文件指定路径,解决方法是将路径相对于文档根目录附加在后面: $filepath = realpath(".") . "/path/to/newfile.txt"; 希望这能帮到大家。

它能够工作,我认为这是最好的解决方案。通过阅读文档,我无法理解它为什么以及如何工作。 realpath() [...] 解析对 /./、/../ 等的引用,并返回规范化的绝对路径名。 好吧,但是.表示当前目录,所以如果将其作为参数传递,它如何被解析为根目录的当前目录?我错过了什么? - funder7
我无法使其工作。在开发工具中,它显示为C:/xampp/htdocs/shipping/styles.css,但如果我打开它,它会重定向到http://localhost/shipping/shipment-details.php/C:/xampp/htdocs/shipping/styles.css,这完全不清楚原因。 - Dgloria

2
echo $pathInPieces = explode(DIRECTORY_SEPARATOR , __FILE__);
echo $pathInPieces[0].DIRECTORY_SEPARATOR;

1

概要

本示例假定您始终知道 Apache 根目录的位置为 '/var/www/',并且您正在尝试查找下一个文件夹路径(例如 '/var/www/my_website_folder')。此外,这适用于脚本或 Web 浏览器,因此需要额外的代码。

PHP7 代码

function getHtmlRootFolder(string $root = '/var/www/') {

    // -- try to use DOCUMENT_ROOT first --
    $ret = str_replace(' ', '', $_SERVER['DOCUMENT_ROOT']);
    $ret = rtrim($ret, '/') . '/';

    // -- if doesn't contain root path, find using this file's loc. path --
    if (!preg_match("#".$root."#", $ret)) {
      $root = rtrim($root, '/') . '/';
      $root_arr = explode("/", $root);
      $pwd_arr = explode("/", getcwd());
      $ret = $root . $pwd_arr[count($root_arr) - 1];
    }

    return (preg_match("#".$root."#", $ret)) ? rtrim($ret, '/') . '/' : null;
}

例子

echo getHtmlRootFolder();

输出:

/var/www/somedir/

详细信息:

基本上,首先尝试获取DOCUMENT_ROOT,如果它包含“/var/www/”,则使用它,否则获取当前目录(必须存在于项目内),并根据$root路径计数获取下一个路径值。注意:添加了rtrim语句以确保在所有情况下路径返回以“/”结尾。它不检查是否需要大于/var/www/,也可以返回/var/www/作为可能的响应。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接