...

View Full Version : detecting path to root vs include path



hessodreamy
08-29-2006, 04:18 PM
What's the best way to determine the path to the document root and thereafter to a relevant include file?

In the past I've used a function which looks at certain variables in the $_SERVER array and works out the path. However this falls down when running cron jobs or some debuggers because the $_SERVER array isn't available.

I was just looking at setting the include path in the ini file, but this seems like it would be fairly slow and inefficient to rely on. ie looking for the file at this location, then that location etc. Seems like it would be slower than just saying where the file is.

The third option I can think of is to manually set a variable containing the file path to the document root. This has portability issues (not major, I know).

For added complication there are occasions where I call an include file from another include file (maybe this is a bad practice, but this is the code i've inherited), so I need to know the path from the original file (hence the __FILE__ constant is not good as it gives the location of the currectly included file).

So what's the best way to do it?

hessodreamy
08-30-2006, 11:26 AM
Thinking about it further, what would be very useful is finding the path to root, for php use, and also for use with html references (javascript files, images, css files etc) which can be used from any file (ie from within includes, and includes within includes - hence precluding use of the __FILE__ constant), at any level, including cron jobs (ie precluding use of $_SERVER variables). Using absolute paths isn't great, as you'll also need to worry about whether you're currently using a secure connection.

I've written a function using the getcwd() function (which I hadn't seen before), and hard coding the document root.


function pathToRoot()
{
$sep = DIRECTORY_SEPARATOR;
$my_docroot = "D:".$sep."web";
$cwd = getcwd();
$path_from_root=str_replace($my_docroot, "", $cwd);
$levels = count(explode($sep,$path_from_root));
$path_to_root = str_repeat("../", $levels -1);

return $path_to_root;
}


That looks like it'll work great.
However...
I'd really like to have the document root in another file, preferably above the document root itself, so I don't accidentally overwrite the settings on the server with the path on my machine. But to call that file, I'd need to use this function, which needs to know the root. I'm in a confused state again. I really don't want to use any hard coding.

Is there a better way?

hessodreamy
08-31-2006, 11:56 AM
So the $_SERVER['PHP_SELF'] value is perfectly good for working out the path, except that it's not available in cron.
I've managed to work around this by setting a DOC_ROOT value in the cron environment, which then becomes accessable to php through the $_SERVER array.
I've included in my function a check to see if PHP_SELF is available and, if not, assume that the file is running under cron and the DOC_ROOT is available, then compare getcwd() with the DOC_ROOT and hence find the path to the document root (which will be the same as the path to the http root)
Here's the function:


function pathToRoot()
{
if(! empty($_SERVER['PHP_SELF']))
{
$this_page = $_SERVER['PHP_SELF'];
$levels_above = substr_count($this_page,"/")-1;
}
else //for cron jobs
{
$sep = DIRECTORY_SEPARATOR;
$my_docroot = $_SERVER['DOC_ROOT'];//this is set in the cron environment
$cwd = getcwd();
$path_from_root=str_replace($my_docroot, "", $cwd);
$levels_above = count(explode($sep,$path_from_root)) -1 ;
}
$path_to_root = str_repeat("../", $levels_above);
return $path_to_root;
}

By jove, I do think I've sorted it. Still miffed that it should be so tricky.

hessodreamy
03-20-2007, 11:51 AM
UPDATE:
I've re-thought this, and it needn't be so hard, in fact the problem needn't really exist at all.

The problem can be mostly solved by 2 points of (what seems to me) general good practice:

1. setting the include path(s) in php.ini, so that you can include a file without knowing your current location. Includes can then be called just by their name (or path relative to the include path in the ini file). So by setting the include path to <docroot>/includes, in your scripts <docroot>/includes/dbconnection.php becomes just dbconnection.php and <docroot>/includes/accounting/calc.php becomes accounting/calc.php
2. Use paths relative to the document root for urls (links, images, scripts etc) (eg. /images/image1.jpg or /products/product.php) where necessary

This covers most usages, including cron jobs and, other command line scripting (where the $_SERVER variables and many other apache specific variables are not available).

The only situation left to resolve is where you need an actual (absolute or relative) file path, for working with files (getting the dimensions of an image, for example).

I've modified my previous function because you really don't need to handle cron jobs separately. Just set the DOCUMENT_ROOT attribute in your cron environment (the same way you would the MAILTO attribute) and it because available in the $_SERVER vars. (This would probably rule out other command line scripts, but I don't really use them)

function pathToRoot()
{
$my_docroot = strtolower((str_replace("\\","/",$_SERVER['DOCUMENT_ROOT']) ));
$cwd = strtolower(str_replace("\\","/",getcwd() ));
$path_from_root=str_replace($my_docroot, "", $cwd);
$levels_above = count(explode("/",$path_from_root)) -1 ;

$path_to_root = str_repeat("../", $levels_above);
return $path_to_root;
}
I've replaced windows backslashes with forward slashes, and made all paths lowercase, for better platform consistency.

Thought this might be handy to anyone else who was having the same headaches I was. :D

aedrin
03-20-2007, 04:18 PM
The ideal thread. One that solves itself. ;)

hessodreamy
03-20-2007, 04:21 PM
slightly more ideal would be one which doesn't take 7 months to do so :)

aedrin
03-20-2007, 06:31 PM
Hehe, I hadn't looked at the date.

I'm amused you looked up the original thread. Nice work ;)



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum