Relative and absolute paths, in the file system and on the web server.

  1. Intro
  2. The difference between absolute and relative paths
  3. Absolute paths
  4. Relative paths
  5. Document root
  6. Web server paths
  7. Current working directory
  8. Console scripts. Single entry point
  9. Helpful PHP commands and constants
  10. Comments (13)

Intro

Your site exists in two realms at once: the real and the virtual one.

For the site visitors it's entirely a virtual server, which in many ways is different from a real one. There are no files for starter. I know, it's hard to believe at first, but it's a fact. In the address like http://example.com/file.html, file.html is not a file. It's a part of URI, a virtual resource. There could be or could be not a real file with such a name, but it doesn't matter. Your browser cannot know that, and don't need to. All it needs to know is an address.

For the site developer, on the other hand, their site is a certain program running on a particular server, on the very real computer with HDD, files and directories. And your PHP script, while reading data files or including other scripts, is working with such real files that exist on the physical medium.

So this dualism is the root of many problems.

PHP users confuse these matters badly at first, doing things like being unable to locate an existing file, confusing hyperlinks with files, including local files via HTTP and such.

However, to sort these things out all you need is to grasp just two simple concepts:

  1. The difference between absolute and relative paths.
  2. The difference between the root of the web server and the filesystem root.

The difference between absolute and relative paths

It's fairly simple.

It's exactly the same as with the real life directions. Given the absolute address, a postal one, like "7119 W Sunset Blvd West Hollywood, CA 90046" you can find the location from anywhere. However, given the relative directions, like "keep three blocks this way and then and turn to the right" would work from the current location only, otherwise sending you astray.

So it goes for the paths in the computer world: given the absolute address, you can always get to the place, no matter from where you started. Whereas relative path is tricky, and should be used with caution, only when you positively know where you are at the moment.

Absolute paths

So again: an absolute path is one starting from the system root

Some absolute path examples:

/var/www/html/forum/index.php
/img/frame.gif
C
:\windows\command.com

Note that in Unix-like systems (and web-servers) the root is defined as a slash - /. And this is very important to know. It is not just a marker, but already a full qualified address, a path. Type cd / in your unix console and you will get to the root directory. Exactly the same is true for all web servers. So you can tell that in the http://example.com/ address the trailing slash is not for the decoration but a regular address itself - the address of the home page.

On Windows, the filesystem doesn't have the common root for the whole system but split between disks, so an absolute paths starts from the drive letter. Whereas each disk has its own root, which is a backslash - \. So you can type cd \ and get to the root of the current disk.

So you can tell that windows is rather confusing, but for the simplicity we would pretend that we have only one disk, and within its boundaries the rules are pretty much the same as in Unix.

So now you can tell an absolute path from a relative one - it is starting from the root, which is:

Relative paths

If you don't supply the root, it means that your path is relative.

The simplest example of relative path is just a file name, like index.html. So one should be careful with relative paths. If your current directory is /about/ then index.html would be one, but if you switch it to /contacts/ then it will be another.

Other relative path examples:

What you ought to know is that the system, when encountered a relative path, always builds it up to the absolute one. Both web-server and file system are doing that but different ways. So, let's learn them.

Document root

This is the most interesting part. There is a point where the real world meets the virtual one.

Imagine there is a file like /var/www/site/forum/index.php. While on the web-server its address is http://www.site.ru/forum/index.php

And here the point can be clearly seen: there is a part, common for both addresses: /forum/index.php, which is the very source of confusion.

For the browser, this path is perfectly absolute, starting from the root of the web-server.
Whereas for the script it's only a part of the full path - the filesystem path. And if you try to use it in PHP it will result in a failure: there is no /forum/ catalog on the HDD!

To get the working path to this file, we have to add the missing part. In our example it's /var/www/site, which is called DOCUMENT_ROOT and is the most important configuration option for the file system interactions. In PHP you can access it via $_SERVER['DOCUMENT_ROOT'].

So now you can tell that to make any file system path work, it should be absolute and built using DOCUMENT_ROOT. So a correct PHP code to access /forum/index.php from PHP would be

$path $_SERVER['DOCUMENT_ROOT'] . "/forum/index.php";

here we are using web-server part of the path, prepending it with the document root. Voila!

Web server paths

are much simpler.

Like it was said before, for the browser, there are no files on the server. A site user never has an access to the server's file system. For the browser, there is a site root only. Which is constant and always simply a slash.

Therefore, to make an HTML link absolute, just build it from the site root - and you will never see a 404 error for the existing file again!

Imagine your site has two sections,

http://www.example.com/about/info.php
and
http://www.example.com/job/vacancy.php

and in the info.php you want to link to vacancy.php. If you make it as is, <a href=vacancy.php>, then browser won't find it! Remember, it always tries to build up the link to the full one, using the current location, which is /about/ and so the resulting path is /about/vacancy.php which is wrong. To make it right, we have to make this link absolute, starting from the site root: /job/vacancy.php

So it goes for all the internal links on the site - images, js and css files, hyperlinks or any other resource that can be clicked on or loaded on the page.

For the local resources it's better to make it path only, without protocol and domain - like /job/vacancy.php. Whereas for the external resources these attributes are obligatory, and so it should be a fully qualified URL like http://www.example.com/job/vacancy.php.

Current working directory

The current working directory (also current directory, working directory, CWD) is the key element in relative paths. It's the directory, from which relative paths being built up.

On a web-server, it's a directory, where the requested php file stays. So if you are requesting an URL like http://example.com/about/index.php, the current working directory would be:

therefore, all relative paths in the HTML on that page will be interpreted by browser as starting from /about:

And likewise, for PHP all relative paths are starting from /var/www/html/about.

In a console, the PHP's current working directory is equal to the shell's current directory. It means that while in /home/user and calling php folder/file.php command, the CWD will be still /home/user.

You can get the current working directory using getcwd() function or change it using chdir().

Console scripts. Single entry point

It's a pity, but for the console scripts our useful $_SERVER['DOCUMENT_ROOT'] variable is unavailable. So we are bound to use paths relative to the calling script, derived from the current script's location.

For example, if your application is hosted in /var/www/app and there are two subfolders, /var/www/app/bin and /var/www/app/config, and you want to access the latter from the former, you can write the following code:

$config_path __DIR__.'/../config/settings.php';
require 
$config_path;

Although technically absolute (starting from a slash), this path is essentially relative to the calling script, because if the calling script will be moved into another directory, it won't find the configuration file anymore.

This is why it is recommended to use a single entry point for your application. Or - as in our case - two entry points, one for web requests and one for console commands.

So for our fictional application we would have three files - an entry point for the web front, an entry point for console applications and a bootstrap file:

Then we could write the following code (among other things) in bootstrap.php:

define('ROOT_DIR'realpath(__DIR__.'/..'));

to define the ROOT_DIR constant that contains the path to our application's root directory (which is directly above the config dir).

And then in both index.php and console.php the

require __DIR__.'/../config/bootstrap.php';

to make all the bootstrap stuff available, including the ROOT_DIR constant. From now on we can use it to build absolute paths starting from the root directory (as long as our scripts are called through the entry point either web or console one):

include ROOT_DIR.'/config/settings.php';

Example implementations can be found in Laravel's Artisan or Symfony Console.

Of course, both entry points should implement a sort of resolver to call all other pages and console scripts but that's slightly out of scope of this article.

Helpful PHP commands and constants

There are may hepful commands and constants in PHP to ease the path interpolation. Some of them are:


Related articles: