The Apache module mod_vhost_alias and its VirtualDocumentRoot directive can really be a great time saver for local development (some googling will explain why in more deapth). Basically, my local dev is set up so that I just have to create a directory in my aliases directory, and I just then navigate my browser to a URL matching the name of that new directory, and apache knows exactly what to serve automagically.

However, there are a few evil gotchas when using mod_vhost_alias, one of which is that the PHP global $_SERVER['DOCUMENT_ROOT'] remains set to the apache default DOCUMENT_ROOT environment variable rather than being re-assigned to the document root activated by the VirtualDocumentRoot directive for the current URL. This can cause some PHP applications (that are too trusting) to die for one reason or another.

I found a great solution to this in the related apache bug report: Simply add the following line to your apache configuration inside the VirtualDocumentRoot vhost definition:

php_admin_value auto_prepend_file /path/setdocroot.php

Then, create the referenced PHP file, and put set this as its contents:

<?php
$_SERVER['DOCUMENT_ROOT'] = str_replace($_SERVER['SCRIPT_NAME'], '', $_SERVER['SCRIPT_FILENAME']);

Now, every page load has this file executed, which properly sets DOCUMENT_ROOT.

  1. Denis.Beurive (not verified) on April 29, 2010 - 5:05am

    Great solution. Thank you for the tip!

  2. Rob Record (not verified) on August 24, 2010 - 10:39am

    This can be improved to allow getenv() to work correctly too. If your document root isn't being set correctly even with the solution above, try putting this in instead:

    <?php apache_setenv("DOCUMENT_ROOT",$_SERVER['DOCUMENT_ROOT'] = str_replace($_SERVER['SCRIPT_NAME'], '', $_SERVER['SCRIPT_FILENAME'])) ?>

  3. Dave (not verified) on September 27, 2010 - 10:42am

    Thanks very much for this fix to a very annoying problem. The solution from Rob did the trick for me.

    Dave

  4. Andrew Otto (not verified) on October 18, 2010 - 3:41pm

    Hmm, good idea! But alas, after trying this I discovered it will not work for me.

    I'm having the same problem, but I think my setup is more complicated. Not only do I reference $_SERVER['DOCUMENT_ROOT'] from PHP, but my .htaccess file uses DOCUMENT_ROOT when doing fancy redirects. I need a way to set this variable from apache before it reaches my .htaccess file and before it reaches PHP.

    Any ideas?

  5. george kom (not verified) on October 24, 2010 - 7:14am

    Andrew, there is a way if you are prepared for an additional step.

    For each virtual host that you need the DOCUMENT_ROOT to be properly set by apache, you can add the following above your 'catchall' virtual host definition.
    <VirtualHost *:80>
      ServerName test.local
      ServerAlias *.test.local
      DocumentRoot /path/to/the/site/root
    </VirtualHost>

    This way the DOCUMENT_ROOT variable for the specified ServerName will be manually set and will override the server's default DOCUMENT_ROOT.

    Note: You will also need to restart Apache after adding a new definition.

  6. Josh on October 24, 2010 - 9:20am

    @george kom -- may not work too well if you are using mod_vhost_alias.

  7. Plushie (not verified) on February 8, 2012 - 9:48am

    Your script didn't work for me if I was using an alias for my directory as the alias path did not exist. I made this one up instead which works for me:

    $SF = explode ("/",$_SERVER['SCRIPT_FILENAME']);
    $SFC = count($SF);
    $SN = explode ("/",$_SERVER['SCRIPT_NAME']);
    $SNC = count($SN);
    $j = 1;
    while ($SF[$SFC-$j] == $SN[$SNC-$j]  && $j < $SFC) {
    	$j++;
    }
    $_SERVER['DOCUMENT_ROOT'] = $SF[0];
    for ($i = 1; $i <= $SFC-$j; $i++) {
    	$_SERVER['DOCUMENT_ROOT'] .= "/".$SF[$i];
    }
    apache_setenv("DOCUMENT_ROOT",$_SERVER['DOCUMENT_ROOT']);

  8. Rodrigo (not verified) on May 29, 2012 - 5:58pm

    Thanks Josh!

  9. Anonymous (not verified) on January 17, 2013 - 7:41am

    Thx man! Saved me a lot of time!

  10. Anonymous (not verified) on March 20, 2013 - 1:42pm

    This does not work on some common setups like HostGator, for which the document root will be something like /usr/local/apache/htdocs, the script filename will be /home/user/public_html/... and the script name may be something like /~user/...

  11. Post new comment

    The content of this field is kept private and will not be shown publicly.
    • Web page addresses and e-mail addresses turn into links automatically.
    • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <blockquote>
    • Lines and paragraphs break automatically.
    • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>, <geshi>, <bash>, <c>, <cpp>, <csharp>, <css>, <drupal5>, <drupal6>, <html>, <js>, <mysql>, <php>, <python>, <rails>, <ruby>, <sql>, <text>, <mssql>, <xml>. Beside the tag style "<foo>" it is also possible to use "[foo]". PHP source code can also be enclosed in <?php ... ?> or <% ... %>.

    More information about formatting options