1 for the money, 10 for the show.
The browser you're using has Javascript turned off. This web page will still work, but it'll work even better if you turn scripting on. Find out how here.
The else{rss} feed will tell you when new geek bits are added to this page. You can click here to subscribe.
 
Subscribe to the else{rss} feed

New geek bits ?

IT ideas, solutions, designs ... gosh, possibly even actual code and software.

You can click the green links at the right to view different subjects. The freshest content is always displayed first, so if what you immediately see isn't new to you, check back later.

If you haven't already read it, check out Inside the Android Dream.

Relatively absolute paths
Wednesday 10 June 2009

Managing paths within a website can be a headache. Required files could be included from multiple levels in the file hierarchy, which means that any files they include then have different relative paths. What's more, the base path relative to the webserver's DocumentRoot can be different on the development PC and the production server. If not consciously planned for, deployment can mean editing file paths in large numbers of website files.

Here's an example. I'm developing a web application in the DocumentRoot of my development Apache installation, but when the application's deployed it'll be in an /application subdirectory on the server. What's more, I have a helper file which may be invoked from the base directory or from various subdirectories - and in some cases I don't know what context a file will be called from, so building a path isn't easy.

One of the atttractions of PHP frameworks like Drupal and Joomla is that they manage this for you, providing a structure that makes including nested files a doddle. But frameworks like these are not the answer to every implementation; the overhead isn't always acceptable.

I've devised an approach that works very well for me. If you find it useful by all means harness it - you can download the code here. It sorts out path issues within an installation, between installations and even gets Javascript references right. Plus it abstracts the physical file locations from the folder names, which increases flexibility. It's simple enough too; at the start of every entry file (controller) I place a single absolute inclusion:

    require (dirname(__FILE__).'/etc/helper_config.php');
Because all entry files are in the same directory, the above line never changes. And because all files loaded after this are within the PHP scope of the entry page, the above require statement is only needed in the one place. After including the above line I can rely on functions within helper_config.php to ensure any required file is correctly addressed, whether we're on my development PC or on the host server. I simply pass the filename preceded by the abstract folder name in a call to one of the helper_config.php functions.

Before we get to the functions, let's talk about this abstract folder name concept. Here are some examples of the entries in my configuration file (also in the downloadable zip file).

    $path_debug = '/etc/debug/';
    $path_files = '/resources/files/';
    $path_floatbox = '/resources/addins/floatbox/';
    $path_modelclasses = '/models/etc/';
    $path_modelhelpers = '/models/etc/';
The variable values above are the physical locations relative to the base directory. The abstract folder names are debug, files, floatbox etc - the part of the variable name after $path_. This approach lets the physical location of files be changed without editing any code except the corresponding entry in the configuration file. You'll also note that some abstract folder names point to the same physical location - using a unique abstract folder name for each different type of file keeps my options open if I later want to restructure.

So what's passed to the helper_config.php file functions is something like "files/scheduledetails.pdf". What comes back depends on the function called and which environment we're in. Here are the functions:

  • path_php($atom) returns the absolute path to the file. If we pass in "files/scheduledetails.pdf" we'll get back one of the following, depending on whether we're on my development PC or the host box:
        C:/DOCUME~1/leigh/MYDOCU~1/MYPROJ~1/else/20090609/resources/files/scheduledetails.pdf
        home/public_html/application/resources/files/scheduledetails.pdf
  • path_url($atom) returns the URL to the file. Passing in the above atom might give us back one of these:
        http://localhost/resources/files/scheduledetails.pdf
        http://www.else.co.nz/application/resources/files/scheduledetails.pdf
  • urlCurrent() returns the URL of the current page:
        http://www.else.co.nz/geekbits.php
  • includeLink($item) writes out an include link for a stylesheet or javascript file; I use this when I'm building page headers. Note that the parameter doesn't need an abstract folder name; it decides what type of file it's been passed based on the extension. On reflection, it may be more consistent (and flexible) to require an abstract folder name but, hey, you've got access to the code, you can change that. For the moment, passing in "core.css" would output this to the page:
        <link rel="stylesheet" type="text/css" 
            href="http://www.else.co.nz/application/resources/styles/core.css" />
  • includeJS() completes the quintet. Calling it when building a page puts a global variable into the page's Javascript scope. The variable g_BaseURL can then be referenced by any Javascript to build accurate URLs when required. If you look at the page source on my production box you might see:
         <script> var g_BaseURL = "http://www/else.co.nz/application/"; </script>

There's one more setting to be aware of in the configuration file. I mentioned above that my approach allows the site to be in a different folder in different environments, relative to the web server's DocumentRoot. This is done by setting the $path_base variable to the folder where the site's located. This setting is an empty string for my development environment, but on the production server you'd see $path_base = 'application';

Use the code in the download for anything you like, and feel free to muck about with it - I'm sure it can be improved. I'd be interested to see any improvements: drop me an email.

If you liked this post
Share/Bookmark
share it around.
If you really liked this post
a small donation helps.
If you liked this post a lot
Subscribe
don't miss the next one.
 
author
LeighLeigh Harrison is currently repaying karma from a past life by working as an IT Generalist in this one.

Leigh lives in New Zealand where she develops web applications and desktop software and manages development projects for clients around the globe. To get a CV send an email or phone +6421 933 913.

In her spare time, and sometimes in other peoples, Leigh writes and occasionally performs music. She hopes to play soccer again next season if her knee will get with the plan.
 
quote
Failure is unimportant. It takes courage to make a fool of yourself.
• Charlie Chaplin
 
links

website
Created by filling a plain text editor with HTML, CSS, PHP, XML, AJAX and any other acronyms that were looking for a good time. There's Javascript, sure, but not in your browser.