Clean URLs – Basic mod_rewrite rules

I’ve been using Comb with a few more projects recently. The main point of Comb is to structure the code in such a way that the request handlers get accessed directly via Apache, as opposed to rewriting the entire URL, and making PHP dynamically include or instantiate a request handling class (i.e. Action, Command, etc).

For example, you might have a registration form that is accessed like this (pseudo-HTTP):

# display the registration page...
GET  /register.php
 
# registration form submits to...
POST /proc_register.php

I personally hate that naming convention because it reminds me of how I wrote code 5 years ago, and it’s just plain ugly.

Here’s a cleaner, friendlier approach that I’d rather use:

# display the registration page...
GET  /register
 
# registration form submits to...
POST /register

Yep, that’s a postback. And yep, there’s no .php extension used to access it, so some URL rewriting will be in order. I’ll add the following code into my virtualhost container in the Apache config:

# turn on the voodoo
RewriteEngine On
 
# if the incoming request has one of these extensions, 
# just serve up the file without rewriting anything
RewriteRule     /*\.(php|html|css|js|jpe?g)$ - [NC,L]
 
# just a little shortcut to make it easier to deal with 
# case-sensitivity
RewriteMap      lc      int:tolower
 
# make clean/friendly URLs work
# e.g., turn this:  GET /register
#       into this:  GET /register_get.php
# 
# and turn this:   POST /register
#     into this:   POST /register_post.php
#
RewriteRule  /(.*)  /$1_${lc:%{REQUEST_METHOD}}.php [NC,QSA,L]

After restarting Apache, I’ll create these two files to make sure the rewrite is working properly:

register_get.php

<html>
<body>
 
  <form method="post">
    Username: <input type="text" name="username" /><br />
    <input type="submit" />
  </form>
 
</body>
</html>

Note the form tag on line #4, it’s simply

without the expected action=”/register” attribute. By leaving the action attribute absent or blank, the browser will simply submit the form back to the current address, i.e., a post-back.

Luckily our rewrite rule will see that the incoming request is a POST instead of a GET, so it’ll route the request into a different script:

register_post.php

<?php
    echo "posting registration form...";
    var_dump($_POST);

Nothing magical happening in there, but the point is that mod_rewrite can be used to run different scripts based on the %{REQUEST_METHOD} variable, so you can organize the scripts according to the action being performed. It would even route PUT, HEAD, and DELETE requests to /register_put.php, /register_head.php, and /register_delete.php, respectively. Assuming the HTTP client was capable of sending those requests (e.g., AJAX).