我有一个应该安装在不同服务器上的 PHP 项目。它有一个includes.php
在项目根目录中命名的包含文件,可以从整个项目的多个位置调用,比如从文件file1.php
(与. 包含文件包含一个函数,该函数应该返回我整个项目的绝对 URL,例如,无论该函数是从哪个文件调用的。includes.php
subdir/file2.php
subdir2/file3.php
http://www.myserver.com/myproject/
- 我不能使用
$_SERVER["REQUEST_URI"]
,因为它返回调用函数的文件的 URL(不同)。我不想传递一个参数说“上两个目录”或类似的东西,因为有很多地方可以调用这个 URL 函数。 - 我不能使用
__FILE__
and$_SERVER['DOCUMENT_ROOT']
(有些人推荐),因为我们的服务器有一些奇怪的配置,比如__FILE__
不在$_SERVER['DOCUMENT_ROOT']
. (我正在为我的学校编写该项目,但它应该分发给其他学校。)
我的最后一个解决方案是采取$_SERVER["REQUEST_URI"]
,删除文件部分并用于get_headers()
检查是否dummy.php
可以在此目录中找到已知文件()。如果没有,我检查父目录等等。不幸的是,get_headers()
在我们的学校服务器中没有返回任何内容(不过,它可以在我家里的测试系统上运行)。
一种可行的解决方案(但我不太喜欢)是将项目根 URL 放在配置文件中。
有人对此有其他想法吗?提前致谢!
编辑:
好的,我自己找到了一个适合我的解决方案。我仍然愿意评论如何做得更好,也许不使用debug_backtrace()
?有理由不使用此功能吗?
function urlPath()
{
$trace = debug_backtrace();
$first_frame = $trace[count($trace)-1];
// the lowest frame gives us the filename from which the first call was made
$callerdir = dirname($first_frame['file']);
$includedir = dirname(__FILE__);
$rootLength = strlen($includedir);
$subDir = substr($callerdir, $rootLength);
$subdirDepth = substr_count($subDir,DIRECTORY_SEPARATOR);
// I use the fact that the include file is in the project root folder, so its
// folder path must be a prefix of any other file's folder path. I remove this
// prefix and count the number of path separators to get the "relative depth".
$pageURL = 'http';
if (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on")
{
$pageURL .= "s";
}
$pageURL .= "://" . $_SERVER["SERVER_NAME"];
if (isset($_SERVER["SERVER_PORT"]) && $_SERVER["SERVER_PORT"] != "80")
{
$pageURL .= ":".$_SERVER["SERVER_PORT"];
}
$pageURL .= $_SERVER["REQUEST_URI"];
// I get the absolute URL of the calling page
for ($i = 0; $i <= $subdirDepth; $i++)
{
$idx = strrpos($pageURL,'/');
$pageURL = substr($pageURL, 0, $idx);
}
// I remove the required number of subdirectories plus one for the filename
return $pageURL;
}