PHP:查找项目根的绝对URL

PHP:查找项目根的绝对URL,php,apache,Php,Apache,我有一个PHP项目,应该安装在不同的服务器上。 它在项目根目录中有一个名为includes.php的包含文件,可以从整个项目的多个位置调用该文件,比如从文件file1.php(与includes.php位于同一位置)、subdir/file2.php和subdir2/file3.php。includes文件包含一个函数,该函数应该返回我整个项目的绝对URL,例如http://www.myserver.com/myproject/,无论从哪个文件调用函数 我不能使用$\u SERVER[“REQ

我有一个PHP项目,应该安装在不同的服务器上。 它在项目根目录中有一个名为
includes.php
的包含文件,可以从整个项目的多个位置调用该文件,比如从文件
file1.php
(与
includes.php
位于同一位置)、
subdir/file2.php
subdir2/file3.php
。includes文件包含一个函数,该函数应该返回我整个项目的绝对URL,例如
http://www.myserver.com/myproject/
,无论从哪个文件调用函数

  • 我不能使用
    $\u SERVER[“REQUEST\u URI”]
    ,因为这会返回调用函数的文件的URL(这会有所不同)。我不想传递一个表示“上两个目录”之类的参数,因为有很多地方可以调用这个URL函数
  • 我不能使用
    \\\\\\\
    $\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\/code>服务器['DOCUMENT\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\/code>的子目录中。(我正在为我的学校写这个项目,但应该分发给其他学校。)
我的最后一个解决方案是使用
$\u服务器[“REQUEST\u URI”]
,删除文件部分,并使用
get\u headers()
检查是否可以在此目录中找到已知文件(
dummy.php
)。如果没有,我检查父目录等等。不幸的是,
get_headers()
在我们的学校服务器中没有返回任何内容(不过它在我家的考试系统上工作)

一个有效的解决方案(但我并不喜欢)是将项目根URL放在配置文件中

有人对此有其他想法吗?提前谢谢

编辑: 好的,我自己找到了一个适合我的解决方案。我仍然对如何做得更好持开放态度,也许不需要使用
debug\u 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;
}
函数urlPath()
{
$trace=debug_backtrace();
$first_frame=$trace[count($trace)-1];
//最低的一帧给出了第一次调用的文件名
$callerdir=dirname($first_frame['file']);
$includedir=dirname(文件名);
$rootLength=strlen($includedir);
$subDir=substr($callerdir,$rootLength);
$subdirDepth=子目录计数($subDir,目录分隔符);
//我使用的事实是,include文件位于项目根文件夹中,因此
//文件夹路径必须是任何其他文件的文件夹路径的前缀。我将删除此选项
//为路径分隔符添加前缀并计数,以获得“相对深度”。
$pageURL='http';
如果(isset($\u服务器[“HTTPS”])&&&$\u服务器[“HTTPS”]=“打开”)
{
$pageURL.=“s”;
}
$pageURL.=“:/”$\u服务器[“服务器名称”];
如果(isset($\u服务器[“服务器\u端口”])和&$\u服务器[“服务器\u端口”]!=“80”)
{
$pageURL.=“:”$\u服务器[“服务器\u端口”];
} 
$pageURL.=$\u服务器[“请求URI”];
//我得到了呼叫页面的绝对URL

对于($i=0;$i我想要类似的东西。但是想要省略文件名

我希望这对你有帮助,伙计!

原始方法:
这花了我一段时间来完善,我把它作为不需要变量的人或项目的一个例子。对于你的情况,你可以做出一个全局的选择

$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__));

或者更简单的方法:)


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


这个“返回项目根url”函数所在的文件是否与项目根有已知的关系?或者您是否有前端控制器(每个请求都在其中发送的文件)?是的,includes.php位于项目根目录中。否,我没有前端控制器。
$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://example.xyz/base/path/without/file/
    http://another.example.com/uploads/test/
    http://www.return.url:81/blah/blahblah/example/