How to programmatically determine the document root in PHP?

20,043

Solution 1

Based on http://www.helicron.net/php/:

$localpath=getenv("SCRIPT_NAME");
$absolutepath=getenv("SCRIPT_FILENAME");
$_SERVER['DOCUMENT_ROOT']=substr($absolutepath,0,strpos($absolutepath,$localpath));     

I had to change the basename/realpath trick because it returned an empty string on my host. Instead, I use SCRIPT_FILENAME. This probably won't work on IIS anymore (but the original scripts that used the $_SERVER variable probably wouldn't either).

Solution 2

In PHP5 there is the magic constant __FILE__ that contains the absolute path of the file in which it appears. You can use it in combination with dirname to calculate the document root.

You can put a statement like the following one in a config file

define ('DOCUMENT_ROOT', dirname(__FILE__));

this should do the trick

Solution 3

There's no need to modify all scripts.

You can run PHP file before any script is run using auto_prepend_file.

$_SERVER is just an array, you can modify it and set correct $_SERVER['DOCUMENT_ROOT'].

Solution 4

This is one reason why people siphon everything through a bootstrap /index.php using htaccess and/or query strings. You can use the dirname( __FILE__ ) trick noted above and get the public base of your app that way.

If you're too far into it to switch to a single entry point, one thing I've seen people do is have a common header to their script which walks up the directory tree to find a file which is unique to the base dir:

function findAppBase( $dir ) {
    if( file_exists( "$dir/unique_file.txt" ) ) {
        return $dir;

    return findAppBase( dirname( $dir ) );
}

$base = findAppBase( dirname( __FILE__ ) );

That code hasn't been tested, and there might be a slicker way using the vars in $_ENV or $_SERVER that will do what you want...

Share:
20,043
Nauman Aslam
Author by

Nauman Aslam

Updated on November 25, 2020

Comments

  • Nauman Aslam
    Nauman Aslam over 3 years

    Here's a problem that I've been running into lately - a misconfigured apache on a webhost. This means that all scripts that rely on $_SERVER['DOCUMENT_ROOT'] break. The easiest workaround that I've found is just set the variable in some global include files that is shared, but it's a pain not to forget it. My question is, how do I determine the correct document root programatically?

    For example, on one host, the setup is like this:

    $_SERVER['DOCUMENT_ROOT'] == '/htdocs'
    

    The real document roots are:

    test.example.com -> /data/htdocs/example.com/test
    www.example.com -> /data/htdocs/example.com/www
    

    And I'd like a script that's run from www.example.com/blog/ (on the path /data/htdocs/example.com/www/blog) to get the correct value of /data/htdocs/example.com/www.

    On another host, the setup is a bit different:

    $_SERVER['DOCUMENT_ROOT'] == '/srv'
    test.example.com -> /home/virtual_web/example.com/public_html/test
    www.example.com -> /home/virtual_web/example.com/public_html/www
    

    Is there any solution to this? Or is the only way simply not to ever rely on $_SERVER['DOCUMENT_ROOT'] and fix all the software that I'm running on my sites? Fixing this on the hosting's side doesn't seem to be an option, I've yet to encounter a host where this is was configured correctly. The best I got was a document root pointing to www.example.com, which was at least inside open_basedir - they used yet another naming scheme, www.example.com would point to /u2/www/example_com/data/www/.

  • Nauman Aslam
    Nauman Aslam over 15 years
    The trick was using both the absolute name of the file (either from the magic constant, or from the server vars) and combine it with the knowledge of the absolute path realtive to the document root from SCRIPT_NAME.
  • SchizoDuckie
    SchizoDuckie over 15 years
    That is kindof useless to run that script on *every run.
  • SchizoDuckie
    SchizoDuckie over 15 years
    That is kindof useless to run that script on every run. Better handle it with some .htaccess instead of setting it.
  • Nauman Aslam
    Nauman Aslam over 15 years
    I'm not sure if it is possible to configure the host correctly, it's seems to be a problem with mod_vhost_alias (according to a comment on webmasterworld.com/apache/3640691.htm).
  • Nauman Aslam
    Nauman Aslam over 15 years
    Thankfully, this isn't a problem, I do have only a single entry point. It's just that I run the same software on multiple domains and hosts, and I have to fix it for each domain. I'd rather submit a fix upstream so I don't have to care about it anymore.
  • Michael
    Michael over 11 years
    From PHP 5.3 this is also __DIR__ use that in stead of dirname(__FILE__).
  • Chuck
    Chuck about 7 years
    But this just returns the folder of the current file which is not necessarily the actual root folder of the webserver.
  • Eineki
    Eineki about 7 years
    Yes @Chuck, you are right, but, if you cannot rely on the $server configuration (I would not do rely on all its values it if not really forced) and do not have a const in place you have to resort to a workaround. The one I proposed is intendet to solve, better to give an hint toward the solution, of this very specific case.