Here y'go.. I didn't know about realpath() when I wrote this, but since this function (so far) works perfectly, I haven't actually tried it. But this is fairly sound, I reckon.
function get_path() {
//ver. 2
/*
$_SERVER['PHP_SELF'] contains the script's absolute url, e.g. [url]www.domain.com/folder/script.php.[/url] This is then exploded by '/'s, which means it's divided by the '/'s it contains, and each bit is part of an array which we call $level (what 'level' of the foldertree you're on, as it were.. ). So [url]www.domain.com/folder/script.php[/url] divided by '/'s returns three parts - [url]www.domain.com,[/url] folder, script.php.
*/
$level = count(explode('/', $_SERVER['PHP_SELF']));
/*
$include_prefix is the variable which will hold all the necessary stuff which'll go in front of our url (relative to the document root), e.g. the '../'s and the folder names. It'll end up having a value something like '../../folder' .
*/
$include_prefix="";
/*
Now we check to see how many parts our url's been divided into.
Then we do stuff, depending on how many parts we got. The lowest number we can get is 2, meaning a file in the root directory, e.g. [url]www.domain.com/script.php[/url] (note: a result of 0 or 1 is actually impossible, since $PHP_SELF always points to a script, so an url of [url]www.domain.com[/url] would actually point to [url]www.domain.com/index.php[/url] - or the file specified as the directory index). If so, append ./ to the include path, since you're in the document root as it is. Remember, our includes are assumed to be relative to this root.
Next, it's 3 parts. That means [url]www.domain.com/folder/script.php.[/url] Here we need to append ../ to the script to get back to the document root, right? Right.
Now, if it's not 2 or 3, then it's 4. Or 5. Or fifty-five, it doesn't matter. We execute a for loop, appending ../ to the $include_prefix for as many times as $i is equal to the $level we're at, MINUS 2. This is important. If you're at level 4, which'd mean something like [url]www.domain.com/folder/subfolder/script.php,[/url] you'd append ../ four times to the variable. We don't want that - in reality, you only need 2 ../'s, one to get out of the subfolder, and one out of the folder, back to the document root. So we subtract 2 from the number of ../ we need. Re-check : If we're at level 5 ([url]www.domain.com/folder/subfolder/anothersubfolder/script.php[/url]) we'd need (5 minus 2) 3 ../s. At level six, we'd need 4. So that's sound.
NOTE: Using this algorithm, a level of '3' isn't strictly necessary as a case in the switch statement, since a level of 3 needs ../ appended once, and 3 minus 2 is 1, but I want to expand this function at some point, to do something when it's at level 3 (to do with my own site's filesystem, something about whether it's an index file, a first-level file, a second-level file etc.. ), so you could just have a case for level 2 and the rest goes in the default code. You can delete case : 3 etc. if you want.. doesn't make any difference to the function's working, just saves three lines.
*/
switch ($level) {
//e.g. [url]www.domain.com/script.php[/url] (2 parts)
case 2:
$include_prefix = './';
break;
//e.g. [url]www.domain.com/folder/script.php[/url] (3 parts)
case 3:
$include_prefix = '../';
break;
//the rest..
default:
for ($i=0; $i<$level - 2; $i++)
{
$include_prefix='../'.$include_prefix;
}
}
/*
Here, we check to see if $include_prefix has a value (it should always have at least ./ ). If it has a value, then return it. Otherwise, exit the script and print that get_path() failed. Which it did, if $include_prefix ends up empty. You don't HAVE to exit the script, I just do, since I use this function to include important page elements like footers and headers and common functions/classes.
*/
if (!empty($include_prefix)) return $include_prefix;
else exit("get_path() failed.");
}
There. I hope that was easy enough to follow. You did say break it down, I rather dissected it. Ahem. Anyway. To use this script, you'd do something like :
function get_path() {
//code ..
}
$inc_path = get_path(); //would return ./ or ../ or ../../ or whatever.
include $inc_path.'images/image.gif'; //should retrieve the file successfully.
Of course, if you're going to use this file to include files from only one directory, you could add this onto the end of the $include_prefix variable before its value is returned. Like :
return $include_prefix.'folder/';
It depends on your needs, really. I tend to do everything relative to the root, 'cause I might not only include files from the 'includes' directory or whatever (even though that's where I've got all the includes from so far, strangely enough..)
I hope this helped. Let me know if it did! Or didn't, in which case I'll accept defeat gracefully.
Cheers,
Alex ...