PHP如何找到应用程序根目录?

30

我有关于包含文件的问题。当我使用 require_once('somefile.php') 时,似乎无法确定如何构建我的URLs。如果我尝试在不同的目录结构中使用一个包含文件,并在多个位置使用它,我会得到一个错误,说找不到该包含文件。

在asp.net中,为了获取我的应用程序根路径,我可以使用~/directory/file.aspx。波浪线斜杠总是知道我正在引用我的网站根目录,并且无论请求从我的网站的哪里来,都能找到该文件。它总是指向根目录并从那里查找文件。

问题:我如何获得我的站点的根路径?我如何做到这一点,以便可以在我的站点的任何地方重用我的包含文件?我必须在我的URL中使用绝对路径吗?

谢谢!


2
URL的构建与require_once无关。URL不是文件,它是HTTP协议的一部分,而不是文件系统。 - Your Common Sense
你使用的是哪个PHP版本,你的文件系统结构是什么样的? - Petah
7个回答

26

有一个$_SERVER['DOCUMENT_ROOT'],应该包含Web服务器的根路径。

编辑:如果您查看大多数PHP程序。在使用安装程序时,通常会输入应用程序文件夹的完整路径。安装程序将在整个应用程序中包含一个配置文件。其中一种选择是使用自动预置文件设置变量。另一种选择是在需要它的每个页面上include_once()配置文件。我建议的最后一种选择是使用引导编写应用程序,其中您将所有请求转发到一个文件(通常带有URL重写)。这使您可以轻松地在一个位置设置/包含配置变量,并使它们在所有脚本中都可用。


在我的开发机上使用WampServer时,当我使用$_SERVER['DOCUMENT_ROOT']时,我会得到C:/wamp/www/。然而,我的网站位于C:/wamp/www/mysite/。如果我的网站托管在像共享主机这样的实时服务器上,当我使用$_SERVER['DOCUMENT_ROOT']时会得到什么? - anon445699
1
这是因为实际应用程序根目录是C:/wamp/www,而您将代码托管在此的子目录中。您可能想要更改此项目的文档根目录或创建一个变量(const MY_APP_ROOT = ...)。 - Dimitrios Mistriotis
1
在实际的托管环境中,比如共享主机,$_SERVER['DOCUMENT_ROOT']会返回我的站点文件夹的路径,对吗? - anon445699
使用 $_SERVER['DOCUMENT_ROOT'] 的问题在于它在 CLI 模式下不可用。因此,如果您从命令行或 CRON 调用脚本,则 $_SERVER['DOCUMENT_ROOT'] 将未定义,并且会出现错误。这就是为什么使用 $_SERVER['DOCUMENT_ROOT'] 是非常糟糕的做法。 - barbushin
@barbushin,如果您从不打算在命令行上运行脚本,我不会说使用服务器变量是“非常糟糕的做法”。我的意思是,我不会在cmd/cron上运行wordpress索引页面。此外,如果您阅读编辑部分,我建议使用配置文件定义一个变量(或常量)来指定路径,以便在不期望更改的地方进行“硬编码”。 - Jonathan Kuhn
显示剩余2条评论

12

我通常将config.php文件存储在根目录中,在config.php中编写:

define('ROOT_DIR', __DIR__);

然后在所有其他脚本中使用ROOT_DIR常量。 使用$_SERVER['DOCUMENT_ROOT']不是很好,因为:

  • 它并不总是匹配根目录
  • 这个变量在CGI模式下不可用(例如,如果您通过CRON运行您的脚本)

5
要在所有其他脚本中使用ROOT_DIR常量,您需要将包含它的文件引入到所有其他脚本中。因此,又面临了同样的问题。 - Your Common Sense
1
是的,但至少你可以使用:include(ROOT_DIR.'/known/path/to/file.php'); 而不是使用类似于:$ROOT = '../../../';(每个子目录都必须更改),但这样你就必须一直担心全局化$ROOT。 - AVProgrammer

1

能够在每个脚本的顶部使用相同的代码,并知道您的页面将正确加载,即使您在子目录中,这非常好。我使用以下代码,它依赖于您知道您的根目录的名称(通常为“ htdocs”或“ public_html”:

defined('SITEROOT') or define('SITEROOT', substr($_SERVER['DOCUMENT_ROOT'], 0, strrpos($_SERVER['DOCUMENT_ROOT'], 'public_html')) . 'public_html');

如果始终定义SITEROOT,您就可以访问配置文件和/或页面组件,而无需逐个脚本地调整路径,例如访问存储在根文件夹外的配置文件:

require_once SITEROOT . "/../config.php";

0

在编程中,你应该使用内置的魔术常量来查找文件,即__FILE____DIR__。如果你使用的是 PHP < 5.3 版本,则应该使用dirname(__FILE__)

例如:

require_once __DIR__.'/../../include_me.php';

$_SERVER['DOCUMENT_ROOT']并不总是能返回你所期望的结果。


为什么它不能在子目录中工作?require_once __DIR__.'/i/am/a/sub/dir.php - Petah
不幸的是,这些解决方案似乎都无法正常工作。$_SERVER['DOCUMENT_ROOT'] 最接近解决方案,但它无法加载包含文件。 - anon445699
我实在是无论如何都没法让它工作。我不得不重写整个函数并将包含的部分注入到一个不同的地方,在那里包含的URL始终相同。这是为了一个授权脚本,用于保护页面,基于用户名、密码和角色。我刚开始接触PHP,我喜欢它,但目前正在经历一些成长的痛苦。除非必须,否则我不会使用ASP.NET。PHP拥有我所需的一切,还有更多。感谢所有的帮助! - anon445699
@anon:对我来说完全正常。也许你的Web服务器配置了错误的文档根目录?我的看起来指向站点的根目录。 - winwaed

-1

在配置文件中定义它。

假设您正在使用 MVC 样式,其中所有内容都通过单个 index.php 路由,那么

realpath('.');

将向您展示当前工作目录的路径(即index.php所在的位置)

然后您可以将其定义为

define('PROJECT_ROOT', realpath('.'));

如果不是MVC且需要它能够处理子文件夹中的文件,那么你可以在配置文件中直接硬编码。
define('PROJECT_ROOT', 'C:/wamp/www/mysite');

然后,当包含某些内容时,您可以执行以下操作;

include PROJECT_ROOT . '/path/to/include.php';

-1

你可以在你的.htaccess文件中设置基础目录。

SetEnv BASE_PATH C:/wamp/www/mysite/

然后在 PHP 中,您可以使用 $_SERVER['BASE_PATH'] 引用它。


如果使用这种范例,每当您的代码被移动到不同的目录或不同的主机上时,您很可能会遇到问题。例如,如果您在Linux服务器上托管,则“C:/wamp/www/mysite/”不会是您的网站所在的位置。我甚至不确定这个路径是否存在于Windows托管服务中。 - McAuley

-3

试试这个:

$_SERVER['DOCUMENT_ROOT']

不是 - OP正在寻找基本URL,而不是文件路径。 - Pekka
1
@Scott 实际上,这个变量的唯一用途是加载包含文件。 - Your Common Sense
正确的写法是: <?php include $_SERVER['DOCUMENT_ROOT'] . "/header.php" ?> ,运行良好。 - winwaed

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