[php] Get Root Directory Path of a PHP project

I have this folder structure in my PHP project. (this is as shown in eclips)

-MySystem
    +Code
    +Data_Access
    -Public_HTML
        +css
        +js
        +Templates
    -resources

When I try this code

echo $_SERVER['DOCUMENT_ROOT']

output is

D:/workspace

How can I get the path to RootDirectory of the system (MySystem), without hardcoding the Folder Name?

This question is related to php

The answer is


you can try: $_SERVER['PATH_TRANSLATED']

quote:

Filesystem- (not document root-) based path to the current script, after the server has done any virtual-to-real mapping. Note: As of PHP 4.3.2, PATH_TRANSLATED is no longer set implicitly under the Apache 2 SAPI in contrast to the situation in Apache 1, where it's set to the same value as the SCRIPT_FILENAME server variable when it's not populated by Apache.
This change was made to comply with the CGI specification that PATH_TRANSLATED should only exist if PATH_INFO is defined. Apache 2 users may use AcceptPathInfo = On inside httpd.conf to define PATH_INFO

source: php.net/manual


I want to point to the way Wordpress handles this:

define( 'ABSPATH', dirname( __FILE__ ) . '/' );

As Wordpress is very heavy used all over the web and also works fine locally I have much trust in this method. You can find this definition on the bottom of your wordpress wp-config.php file


echo $pathInPieces = explode(DIRECTORY_SEPARATOR , __FILE__);
echo $pathInPieces[0].DIRECTORY_SEPARATOR;

When you say that

$_SERVER['DOCUMENT_ROOT']

contains this path:

D:/workspace

Then D: is what you are looking for, isn't it? In that case you could explode the string by slashes and return the first one:

$pathInPieces = explode('/', $_SERVER['DOCUMENT_ROOT']);
echo $pathInPieces[0];

This will output the server's root directory.

Update: When you use the constant DIRECTORY_SEPARATOR instead of the hardcoded slash ('/') this code is also working under Windows.

Update 2: The $_SERVER global variable is not always available. On command line (cli) for example. So you should use __DIR__ instead of $_SERVER['DOCUMENT_ROOT']. __DIR__ returns the path of the php file itself.


At this moment, PHP itself does not provide a way to get the project's root directory for sure.

But you can implement a very simple method yourself that will do exactly what you're looking for.

Solution

Create a new file in your project, let say D:/workspace/MySystem/Code/FilesManager.php (use whatever name and path suit you the best). Then, use the following code:

<?php

class FilesManager
{
  public static function rootDirectory()
  {
    // Change the second parameter to suit your needs
    return dirname(__FILE__, 2);
  }
}

Now you can do this in, let's say D:/workspace/MySystem/Code/a/b/c/Feature.php:

echo FilesManager::rootDirectory();

And the expected result should be:

"D:/workspace/MySystem"

The output will be the same no matter where your "feature" file is located in the project.

Explanation

dirname is used to return the parent directory of the first parameter. We use the magic constant __FILE__ to give it FilesManager.php's path. The second parameter tells how many times to go up in the hierarchy. In this case, we need to do it twice, but it really depends where you put your file in the hierarchy. You can omit the second parameter if you only need to got up once, meaning the file is located in the root. But then, you can return __DIR__ directly instead.

This solution is guaranteed to work, no matter where the root is located on your server. Unless you end up moving the utility class somewhere else in the hierarchy.

Additional note

I'd avoid using DOCUMENT_ROOT for the following reasons (according to this answer):

  • It makes your application dependent on the server.
  • The Apache setup may give an incorrect path to the root directory.

Summary

This example assumes you always know where the apache root folder is '/var/www/' and you are trying to find the next folder path (e.g. '/var/www/my_website_folder'). Also this works from a script or the web browser which is why there is additional code.

Code PHP7

function getHtmlRootFolder(string $root = '/var/www/') {

    // -- try to use DOCUMENT_ROOT first --
    $ret = str_replace(' ', '', $_SERVER['DOCUMENT_ROOT']);
    $ret = rtrim($ret, '/') . '/';

    // -- if doesn't contain root path, find using this file's loc. path --
    if (!preg_match("#".$root."#", $ret)) {
      $root = rtrim($root, '/') . '/';
      $root_arr = explode("/", $root);
      $pwd_arr = explode("/", getcwd());
      $ret = $root . $pwd_arr[count($root_arr) - 1];
    }

    return (preg_match("#".$root."#", $ret)) ? rtrim($ret, '/') . '/' : null;
}

Example

echo getHtmlRootFolder();

Output:

/var/www/somedir/

Details:

Basically first tries to get DOCUMENT_ROOT if it contains '/var/www/' then use it, else get the current dir (which much exist inside the project) and gets the next path value based on count of the $root path. Note: added rtrim statements to ensure the path returns ending with a '/' in all cases . It doesn't check for it requiring to be larger than /var/www/ it can also return /var/www/ as a possible response.


use the PHP function:

getcwd()

Gets the current working directory.


You could also use realpath.

realpath(".") returns your document root.

You can call realpath with your specific path. Note that it will NOT work if the target folder or file does not exist. In such case it will return false, which could be useful for testing if a file exists.

In my case I needed to specify a path for a new file to be written to disk, and the solution was to append the path relative to document root:

$filepath = realpath(".") . "/path/to/newfile.txt";

Hope this helps anyone.