Directory based URLs with Apache/PHP

Table of contents

Updated: 20 April 2010

Introduction

This tutorial will outline how to configure Apache to accept directory based URLs using only the .htaccess file. Example code will be provided demonstrating how to interpret these directory URLs in PHP and retrieve the correct information.

Example of the old and ugly query string URL:

http://www.freeangle.com/photos.php?expo=canada&index=24

Example of the new and pretty search engine friendly URL:

http://www.freeangle.com/photos/canada/24/

Requirements

This tutorial assumes that Apache HTTP Server (1.3 or 2.0) and PHP (4 or 5) have been setup correctly as outlined in our Install and Setup Apache/PHP tutorial.

Important: PHP must be installed as an Apache module (not a CGI script) to be able to correctly interpret directory based URLs.

What is the .htaccess file?

.htaccess files (or "distributed configuration files") provide a way to make configuration changes on a per-directory basis. A file, containing one or more configuration directives, is placed in a particular document directory, and the directives apply to that directory, and all subdirectories thereof. http://httpd.apache.org/docs/howto/htaccess.html

If your website is being hosted by a web-hosting company, you may not have the ability to directly edit Apache's httpd.conf file. Thus, .htaccess files provide a convienent way to change Apache's configuration settings.

Note: Double-check that your web-hosting company supports the use of .htaccess files and what level of access is allowed.

Setup AllowOverride to allow .htaccess files

Make sure that the website directory has the proper access rights to allow custom configuration from the .htaccess file.

Specifying directory access rights is done with the Directory definition in Apache's httpd.conf file. For the .htaccess file, the important part is the AllowOverride line.

Edit Apache's httpd.conf file found in the ...\Apache2\conf\ directory.

<Directory "D:/web/freeangle">
   Options Indexes FollowSymLinks
   AllowOverride All
   Order allow,deny
   Allow from all
</Directory>

Note: Apache must be restarted before these changes come into effect.

Note: Where this Directory definition is setup depends on whether your website is being referenced through the DocumentRoot, through an Alias, or as a VirtualHost. Please read our Reference local directory as website tutorial for more information.

Create extension-less file

As stated before, we want to turn this query string URL:

http://www.freeangle.com/photos.php?expo=canada&index=24

... into this directory based URL:

http://www.freeangle.com/photos/canada/24/

The trick is that /photos/ is not a directory but rather an extension-less PHP file. Using the example above, save the original photos.php file as photos (with no file extension) into the root directory of your website.

Note: The link http://www.freeangle.com/photos/ won't work yet because Apache doesn't know how to process the extension-less file (photos). This is where the .htaccess file comes in.

Use .htaccess to ForceType extension-less files

Create a new text file with the following content:

<Files photos>
   ForceType application/x-httpd-php
</Files>

Save this file as .htaccess and place it in the root directory of your website.

Apache will now execute PHP for your extension-less photos file. Also, be aware that Apache will launch the photos file for all references to the /photos URL.

Note: A new Files section must be added to the .htaccess file for every extension-less file you wish to use.

<Files about>
   ForceType application/x-httpd-php
</Files>
<Files contact>
   ForceType application/x-httpd-php
</Files>
<Files photos>
   ForceType application/x-httpd-php
</Files>

PHP code to process directory string URLs

With both the .htaccess file and the photos file in the root directory of our website, we are now able to create beautiful directory based URLs such as:

http://www.freeangle.com/photos/

http://www.freeangle.com/photos/canada/24/

To retrieve the URL information that comes after the /photos part (i.e. "/canada/24/") use the following PHP function:

function get_dir_query_string()
{
   // Split up URL path string into an array
   $aPathInfo = explode("/", $_SERVER["PATH_INFO"]);
   // Remove the first array element "/"
   array_shift($aPathInfo);
   // Return array
   return $aPathInfo;
}

At the top of the photos file, call the get_dir_query_string() function to get the directory string parameters from the URL.

// Example #1
// http://www.freeangle.com/photos/canada/24/
list($sCategory, $iIndex) = get_dir_query_string();
echo $sCategory;
// Prints "canada"
echo $iIndex; // Prints "24"

// Example #2
// http://www.freeangle.com/photos/dir/strings/rock/
$aParams = get_dir_query_string();
echo $aParams[0];
// Prints "dir"
echo $aParams[1]; // Prints "strings"
echo $aParams[2]; // Prints "rock"

User comments

Hi,

We have Directory based URLs with Apache running with any problems on apache version 1.3.27.

But we are now migrating two a new server with Apache version 2.0.46 and the Directory based URLs are not working any more.

Have you heard abaut this problem?

Kind regards,
JW

JW

Hi JW,

I've had problems with Apache 2.0 and directory based URLs if PHP is setup as a CGI script (and not as an Apache module).

See the Setup Apache/PHP tutorial for details:
PHP4: http://www.freeangle.com/article/setup_apache_php/#section5.1
PHP5: http://www.freeangle.com/article/setup_apache_php/#section5.2

If this doesn't help, please provide more details as to what exactly is the problem and when it is occuring.

Aaron Schmidt

Add your comment

*
*