RewriteMap TXT
So we all know that mod_rewrite will destroy your brain cells faster than any other voluntarily ingested toxin, and yet we all seem to inhale it all the time. In my new found love of design patterns, regular expressions a.k.a regex (the primary fuel behind all matters rewrite) has become an essential tool in my arsenal of solutions to every day problems.
Unfortunately most of the material available relating to mod_rewrite, .htaccess and the different flavors of regular expression never seems to quit communicate the proper ways (note: plural here) of understanding and implementing mod_rewrite. Note: I’m running on assumption here that you have some knowledge of how to translate regular expression and if not I’d suggest going through the basics over at Zytrax’s regex user guide or dive straight into the Perl Regular Expression manual.
RewriteMap.
You can choose to implement RewriteMap in various ways but i choose the text file route because its relatively easier to implement, does not require external execution (prg : requires command line execution of your rewrite program), and is easier to troubleshoot.
problem:
rewrite and redirect this old urls
http://example.com/shoes/item.php?id=1245&size=medium
to something descent like
http://example.com/shoes/ladies/sandals/
Solution:
Create your rewrite map map.txt
# old shoes urls
1245 ladies/sandals
1024 mens/boots
5487 ladies/boots
Add the following to your httpd.conf inside your virtual host directive .
# if your path has spaces just place it in quotes
RewriteMap legacy "txt:c:/path to text file/map.txt"
RewriteCond %{THE_REQUEST} ^GET\ /([\w-]+)/(.*)\.php/\?id=([\d]+)(.*)
RewriteRule ^(.*)$ ${legacy:%3}/? [R=301,L]
Explanation:
- The map.txt:
- simple text file that has the value we are looking for (1245) and the value we want to replace it with (ladies/sandals)
-
RewriteCond %{THE_REQUEST} - This will try and match the whole URL request sent to the server.
I used this instead of the more commonly touted RewriteCond %{QUERY_STRING} because %{THE_REQUEST} captures the whole URL including the query string and since i am well aware of the URL format i can do an exact query string match of my URL without incurring the overhead of a greedy check of whether the query string exists or not, while validating the value of the variable i need to rewrite -
RewriteRule ^(.*)$ ${legacy:%3}/? [R=301,L] - This will take the whole URL, replace it with my matched value (${legacy:%3}), remove the query string by adding a ‘?’ and permanently redirect the URL to the new one ‘[R=301,L]‘
magic .. don’t you think?