Determining the Base Path in PHP

Determining the Document Root, also known as the Base Path, is important when you want to include files or work with the file system; this solution should be very flexible and broadly compatible.

2944 views
d

By. Jacob

Edited: 2021-02-28 16:14

When including files or working with the file system from PHP scripts, it is best to use absolute paths; however, knowing the base path of a project can actually be quite difficult, since there might be inconsistencies between systems. Instead, I now define my own BASE_PATH at the composition root of my projects (Usually the index.php file).

The problem is that the document root might not refer to what we expect, and it has other inconsistencies as well, such as missing a tailing slash on directories. To avoid this, I now define my own base path variable, using forward slash as directory separator — and for directories, a tailing slash is always be included.

All paths should be written using forward slash as directory separator, since this is supported by most systems.

Windows will also work just fine using forward slash — in fact, even using a mix of backslash and forward slash should work fine — for consistency, it is however best if we use the same throughout the code.

Another reason for this policy is that backslash might cause problems in some circumstances, since it has special meaning in PHP, and therefore needs to be escaped when used in paths, even when used within single quotes..

From PHP 5.3 and onwards, we can use __DIR__:

define('BASE_PATH', rtrim(preg_replace('#[/\\\\]{1,}#', '/', __DIR__), '/') . '/');

In older versions:

define('BASE_PATH', rtrim(preg_replace('#[/\\\\]{1,}#', '/', realpath(dirname(__FILE__))), '/') . '/');

Handling includes

At the top of an index file we usually define a BASE_PATH constant. This constant can be used when including files via include or require, and can also be accessed from within the included files, though this is best avoided.

If some class methods depends on BASE_PATH, it is probably better to pass it as an argument to the method, or via dependency injection through a settings object.

Below is an example of how BASE_PATH is defined:

define('BASE_PATH', rtrim(preg_replace('#[/\\\\]{1,}#', '/', realpath(dirname(__FILE__))), '/') . '/');

The code works like this:

  1. realpath(dirname(__FILE__)) creates the absolute path for the parent directory of the running script.
  2. preg_replace makes sure we only use forward slash as separator. Note. Backlash needs to be escaped like this "\" when used in regular expressions.
  3. rtrim() removes a trailing slash (if any).
  4. Finally a trailing slash is added manually. This is needed to avoid confusion when using the BASE_PATH constant.

Dynamically including files

Currently developers need to remember using forward slash consistently. This is not a huge problem since most will probably be developing on Linux anyway. But, a solution could be to include files via a function or asset loader instead.

This is not something we are currently doing, but it would also be a useful way to dynamically include files if this is something we might need in the future.

$files_to_include = array(
  BASE_PATH . 'lib/db_class/db_class.php',
  BASE_PATH . 'lib/translator/translator_class.php'
);

function dynamic_require($files_array) {
  foreach ($files_array as $file) {
   require preg_replace('#[/\]{1}#', '/', $file);
  }
}

DIRECTORY_SEPARATOR is not recommended

It is not recommended that developers use DIRECTORY_SEPARATOR, since most systems will understand forward slash just fine. There might still be niche cases where it can be useful, but we avoid it for includes.

DIRECTORY_SEPARATOR is a predefined constant in PHP. It contains the default directory separator used on the system where the script is running.

Tell us what you think:

  1. In this Tutorial, it is shown how to redirect all HTTP requests to a index.php file using htaccess or Apache configuration files.
  2. How to create a router in PHP to handle different request types, paths, and request parameters.
  3. Tutorial on how to use proxy servers with cURL and PHP
  4. When using file_get_contents to perform HTTP requests, the server response headers is stored in a reserved variable after each successful request; we can iterate over this when we need to access individual response headers.
  5. How to effectively use variables within strings to insert bits of data where needed.

More in: PHP Tutorials