2

我有一个应该安装在不同服务器上的 PHP 项目。它有一个includes.php在项目根目录中命名的包含文件,可以从整个项目的多个位置调用,比如从文件file1.php(与. 包含文件包含一个函数,该函数应该返回我整个项目的绝对 URL,例如,无论该函数是从哪个文件调用的。includes.phpsubdir/file2.phpsubdir2/file3.phphttp://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;
}
4

1 回答 1

2

我想要类似的东西。但是希望省略文件名。

我希望这对伴侣有帮助!

RAW 方法:
这花了我一段时间来完善,我将作为不需要变量的人或项目的示例。对于你的情况,你可以做一个全局的。

$current_url = (empty($_SERVER['HTTPS']) ? "http://" : "https://") . ($_SERVER['SERVER_NAME']) . (((empty($_SERVER['HTTPS']) ? 'http' : 'https') == "http" && $_SERVER['SERVER_PORT'] == 80 || (empty($_SERVER['HTTPS']) ? 'http' : 'https') == "https" && $_SERVER['SERVER_PORT'] == 443) ? "" : ":" . $_SERVER['SERVER_PORT']) . (preg_replace("!^". preg_replace("!". $_SERVER['SCRIPT_NAME'] ."$!", "", $_SERVER['SCRIPT_FILENAME']) ."!", "", __DIR__));


或者,更简单的方法:)

$protocol = ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
$path = substr( dirname(__FILE__), strlen($_SERVER['DOCUMENT_ROOT']));
$current_url = $protocol . $_SERVER['HTTP_HOST'] . $path;


示例输出:(https、http、端口等)

    https://example.xyz/base/path/without/file/
    http://another.example.com/uploads/test/
    http://www.return.url:81/blah/blahblah/example/
于 2015-08-16T15:42:53.563 回答