Reputation: 59
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.php
and 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.
$_SERVER["REQUEST_URI"]
because that returns the URL of the file calling the function (which varies). I don't want to pass a parameter that says "go up two directories" or something like that because there is a huge number of places this URL-function can be called from.__FILE__
and $_SERVER['DOCUMENT_ROOT']
(which is recommended by some) because our server has some strange configuration such that __FILE__
is not in a subdirectory of $_SERVER['DOCUMENT_ROOT']
. (I am writing the project for my school but it is supposed to be distributed to other schools.)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
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