PHP 包含相对路径

我有一个文件/root/update/test.php

include "../config.php";

在/root/update/test.php 中

set_include_path(".:/root");
include "connect.php";

当我运行/root/update/test.php 时,它会找到 connect.php,但是找不到 config.php

PHP Warning:  include(../config.php): failed to open stream: No such file or directory in /root/connect.php on line 2
PHP Warning:  include(): Failed opening '../config.php' for inclusion (include_path='.:/root')

这让我感到困惑,因为这些警告让我觉得我所做的一切都是正确的—— include 路径是/root,它正在查找 file。./config.php (/config.php) ,它存在。有人能帮我解释一下吗?请注意,对我来说,使用绝对路径不是一个选项,因为要将其部署到我无法访问的生产服务器。

Ubuntu/Apache

147341 次浏览

While I appreciate you believe absolute paths is not an option, it is a better option than relative paths and updating the PHP include path.

Use absolute paths with an constant you can set based on environment.

if (is_production()) {
define('ROOT_PATH', '/some/production/path');
}
else {
define('ROOT_PATH', '/root');
}


include ROOT_PATH . '/connect.php';

As commented, ROOT_PATH could also be derived from the current path, $_SERVER['DOCUMENT_ROOT'], etc.

You could always include it using __DIR__:

include(dirname(__DIR__).'/config.php');

__DIR__ is a 'magical constant' and returns the directory of the current file without the trailing slash. It's actually an absolute path, you just have to concatenate the file name to __DIR__. In this case, as we need to ascend a directory we use PHP's dirname which ascends the file tree, and from here we can access config.php.

You could set the root path in this method too:

define('ROOT_PATH', dirname(__DIR__) . '/');

in test.php would set your root to be at the /root/ level.

include(ROOT_PATH.'config.php');

Should then work to include the config file from where you want.

function relativepath($to) {
$a=explode("/",$_SERVER["PHP_SELF"] );
$index= array_search("$to",$a);
$str="";
for ($i = 0; $i < count($a)-$index-2; $i++) {
$str.= "../";
}
return $str;
}

Here is the best solution i made about that, you just need to specify at which level you want to stop, but the problem is that you have to use this folder name one time.