Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 7 of 7
  1. #1
    New Coder
    Join Date
    May 2005
    Location
    Leeds, UK
    Posts
    83
    Thanks
    1
    Thanked 0 Times in 0 Posts

    detecting path to root vs include path

    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?

  • #2
    New Coder
    Join Date
    May 2005
    Location
    Leeds, UK
    Posts
    83
    Thanks
    1
    Thanked 0 Times in 0 Posts
    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.
    PHP Code:
    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?

  • #3
    New Coder
    Join Date
    May 2005
    Location
    Leeds, UK
    Posts
    83
    Thanks
    1
    Thanked 0 Times in 0 Posts
    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:
    PHP Code:
    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)) -;
        }    
        
    $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.

  • #4
    New Coder
    Join Date
    May 2005
    Location
    Leeds, UK
    Posts
    83
    Thanks
    1
    Thanked 0 Times in 0 Posts
    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)
    Code:
    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.

  • #5
    Senior Coder
    Join Date
    Jan 2007
    Posts
    1,648
    Thanks
    1
    Thanked 58 Times in 54 Posts
    The ideal thread. One that solves itself.

  • #6
    New Coder
    Join Date
    May 2005
    Location
    Leeds, UK
    Posts
    83
    Thanks
    1
    Thanked 0 Times in 0 Posts
    slightly more ideal would be one which doesn't take 7 months to do so

  • #7
    Senior Coder
    Join Date
    Jan 2007
    Posts
    1,648
    Thanks
    1
    Thanked 58 Times in 54 Posts
    Hehe, I hadn't looked at the date.

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


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •