LeRainieur
LeRainieur

Reputation: 59

PHP: Find absolute URL of project root

I have a PHP project that is supposed to be installed on different servers. It has an include file named includes.php in the project root directory that can be called from several locations throughout the project, let's say from files file1.php (in the same location as includes.php), subdir/file2.phpand subdir2/file3.php. The includes file contains a function that is supposed to return the absolute URL of my entire project, for example http://www.myserver.com/myproject/, no matter from which file the function was called.

My last solution was to take $_SERVER["REQUEST_URI"], remove the file part and to use get_headers() to check if a known file (dummy.php) can be found in this directory. If not, I check the parent directory and so on. Unfortunately, get_headers() doesn't return anything in our school server (it works on my test system at home, though).

One solution that works (but that I don't really like) is to have the project root URL in a config file.

Does anyone have another idea for that? Thanks in advance!

Edit: OK, I found a solution on my own that works for me. I am still open to comments how to do it better, maybe without using debug_backtrace()? Is there a reason not to use this function?

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;
}

Upvotes: 2

Views: 661

Answers (1)

do loop
do loop

Reputation: 77

I wanted something similar. However wanted the file name omitted.

I hope this helps mate!

RAW Approach:
This took me a while to perfect, and I kept as an example for people or projects where no variables are required. For your situation, you can make a global.

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


OR, Simpler Approach :)

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


Example Output: (https, http, port, etc)

    https://example.xyz/base/path/without/file/
    http://another.example.com/uploads/test/
    http://www.return.url:81/blah/blahblah/example/

Upvotes: 2

Related Questions