Article

mod_rewrite: A Beginner's Guide to URL Rewriting

Page: 1 2 3 4

For Advanced Users

I mentioned user-friendliness in the introduction, and haven't dealt with it. First, let's imagine we're having a huge download site that has the downloadable software separated into categories, each with a unique id (which is used in the SQL SELECTs). We use links like open.php?categoryid=23487678 to display the contents of a category.

To ensure that our URLs were easily memorized (eg. http://www.downloadsite.com/Nettools/Messengers) we could use:

 RewriteRule ^/NetTools$ /test.php?target=3    
 RewriteRule ^/NetTools/Messengers$ /test.php?target=34

assuming the ID is 3 for the NetTools category and 34 for Messengers subcategory.

But our site is huge, as I've mentioned - who wants to hunt down all the IDs from the database, and then edit the config file by hand? No-one! Instead, we can use the mapping feature of mod_rewrite. Map allows us to provide a replacement-table - stored in a single text file -- within a hash file (for fast lookups), or even served through an external program!

For better performance I'd generate a single text file using PHP, which contains the following:

 NetTools            3    
 NetTools/Messengers 34    
 .    
 .    
 .    
 and so on.

The httpd.conf file would contain:

 RewriteMap categories txt:/path/to/file/categoryids.txt    
 RewriteRule ^(.*)$ open.php?categoryid=${categories:$1|0}

These lines tell mod_rewrite to read the categoryids.txt file upon Apache startup, and provide the ID for the URL for open.php. The |0 means that categoryid will be 0 if there's no matching key in the textfile.

You can also choose to serve the IDs on-the-fly via a script or other executable code. The program is started by Apache on server startup, and runs until shutdown. The program must have buffered I/O disabled, read from the stdin, and write results to stdout -- it's that simple!

With RewriteMap you can do a lot more, including:

  • load balancing through servers (using rnd:),
  • creation of a Webcluster that has an homogenous URL layout,
  • redirection to mirror sites without modifying your Web application,
  • denial of user access based on a hostlist,

and so on.

Tips, Tricks and Advice

  1. Before using mod_rewrite in a production server, I'd recommend setting up a testserver (or playground, whatever you prefer to call it).
  2. During development, you must avoid using 'old-fashioned' URLs in your application.
  3. There might still be need to verify data passed through the URL (passing non-existing -- too large or small - IDs, for example, might be risky).
  4. Writing 'intelligent' RewriteRules saved me coding time and helped me write simpler code. I'm using error_reporting(E_ALL); everywhere (and I recommend it!), but I find it boring to do the following for the ten thousandths time:

    if (isset($_GET['id']) && (validNumber($_GET['id']))    
    if (isset($_GET['todo']) && ($_GET['todo']=='deleteitem'))

    The following trick helped me to get rid of the extra isset() expression by providing all the needed parameters each time in the RewriteRules:

    RewriteRule ^/products/[0-9]+$ products.php?id=$1&todo=

    I know, I know it's not the answer to the meaning of life -- but it's hard to show how nice and clear a solution this might provide in such a short example.

Finally...

That's all for our 'brief' overview of mod_rewrite. After you've mastered the basics, you'll find you can easily create your own rules. If you like the idea of URL rewriting, may want to play with mod_rewrite - some ideas follow (note that the underlying PHP code is not important in this case):

http://www.mysite.com/1/2/3/content.html    
   => 1_2_3_content.html    
   http://www.mysite.com/1/2/3/content.html    
   => content.php ? category=1    
   
   http://www.mysite.com/1/2/3/    
   => content.php ? category=1 & subcat1 = 2 & subcat2 = 3    
   
   http://www.mysite.com/1/2/3/details    
   => content.php ? category=1 & subcat1 = 2 & subcat2 = 3    
   http://www.mysite.com/bookshop/browse/bytitle    
   => library.php ? target=listbooks & order = title    
   http://www.mysite.com/bookshop/browse/byauthor    
   => library.php ? target=listbooks & order = author    
   
http://www.mysite.com/bookshop/product/123    
   => library.php ? target=showproduct & itemid=123    
   
http://www.mysite.com/bookshop/helpdesk/2    
   => library.php ? target=showhelp & page=2    
  http://www.mysite.com/bookshop/registration    
   => library.php ? target=reg

Links

If you liked this article, share the love:
Print-Friendly Version Suggest an Article

Sponsored Links

Rate This Article

  • 1
    Poor
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
    Great

Comment on This Article

Have something to say?

Post A Comment

You need to be a member of the SitePoint Forums to comment on this post. Sign Up

Already a member? Post using your SitePoint Forums account: