Whenever I create a web site, I use functions to output the header and footer of each page. This technique allows easy editing of page layouts as most of the HTML resides in these two functions. Every page on the site will call the same two functions, resulting in a consistent look and feel across the whole web site.
The header function outputs the <head> section of the HTML, which will normally contain links to style sheets. The question is: should these links be relative or absolute?
Relative links
The problem with relative links rears its ugly head when the header function is called from different directory depths. Take, for example, the following directory structure:
/css/main.css
/members/admin/index.php [1]
/members/index.php [2]
It’s clear to see that file [1] requires a different relative link to access the CSS file compared with file [2] (i.e. ../../css/main.css versus ../css/main.css). A static relative link won’t work for every file in a web site.
Absolute links
What about an absolute link? This would certainly solve the above problem, however it presents its own irritating issue: what to do if the folder structure changes?
To give an example, my local web server is configured to serve pages from /var/www and I create a subdirectory for each site I’m constructing. So my work on http://www.foo.com will probably be stored in /var/www/foo and accessed as http://localhost/foo on my test server. Unfortunately, this means that absolute links on my test server (e.g. /foo/css/main.css) will break on my production server (which would require /css/main.css).
Solution
One solution is to define a base bath, as follows:
define("BASE_PATH", dirname(substr(__FILE__, strlen($_SERVER['DOCUMENT_ROOT']) -1)));
Let’s break the definition into pieces to see what this code is doing:
- The
__FILE__constant will output the full path of the current file from the web server’s point of view, e.g./var/www/mysite/foo/bar.php. - The
$_SERVER['DOCUMENT_ROOT']variable will output the directory from which the web server is serving files, e.g./var/www. - The
substrcommand effectively subtracts one from the other, leaving/mysite/foo/bar.php. - The
dirnamecommand strips off the file name, leaving/mysite/foo.
Now, suppose my bar.php file contains the header function. It’s now able to construct an absolute link to anywhere in the web site, by prefixing the BASE_PATH constant to a relative link, e.g.:
$link = BASE_PATH . '/../css/main.css';
This forms an absolute link that is resilient to the folder structure changes discussed above.