Beginner’s Mod_Rewrite Tutorial | edrackham




Have you seen those websites such as Digg and SVP that use fancy URLs such as http://domain.com/page_content? Yeah, sure this could be nearly achieved by simply renaming your pages to something like page_content.htm – but that would result in you having to change every page on your site to a suitably written filename, as well as relying on static pages. I’m going to attempt to demonstrate just how easy it really is to utilise mod_rewrite to have fancy – even “web 2.0″ – URLs within your site.

Mod_rewrite is useful for pages with dynamic content, such as those which rely on either POST or GET data to generate the content. A URL that looks something like

http://domain.com/product.php?product_id=19

would be ideal to control using mod_rewrite. The main reasons being that:

  1. The URL is referencing dynamic content (as the GET suggests in the URL).
  2. The page, product.php, will remain the same – yet load different data based on the value of the GET variable ‘product_id’.

So let’s get started shall we? If you know mod_rewrite works, start masking pages with mod_rewrite now!.

Testing Mod_Rewrite Works

In order to use mod_rewrite, you will need the following:

  • The module ‘mod_rewrite’ enabled.
  • Either have direct access to your httpd.conf file which won’t be entirely discussed in this tutorial, or have the ability to use .htaccess files within your site.
  • Have the AllowOverride directive within the httpd.conf file set to allow rules for you to use mod_rewrite commands.

Don’t panic – most Apache web servers have the above enabled and ready to go! Let’s do a simple test to make sure everything is cool to go. Create a .htaccess file in your site’s root directory.

Insert the following text into your new .htaccess file:

Options +FollowSymLinks
Options +Indexes
RewriteEngine On

NOTE: The .htaccess file will affect all files within the same directory as itself, as well as sub-directories and their respective files. The directory can change, but for the purposes of this tutorial, we’re gonna stick this bad boy in your root directory.

Upload your .htaccess file to the root directory of your site, and load the index page (well, any valid page for that matter!). One of two things will happen (at least, I think I’m right here…). You’ll find that either:

  • Your requested page loads just fine. Good.
  • You get an Internal Server Error (500). Bad.

If you get the Internal Server Error (error 500), I’m afraid that it looks like either mod_rewrite isn’t installed, or your httpd.conf file doesn’t allow the required AllowOverride directives. If this is the case, and you do have access to edit your httpd.conf file, do so and set AllowOverride to ALL for your site root directory:

<Directory "/var/www/sites/www.domain.com">
AllowOverride All

NOTE: You can also add all of the mod_rewrite rules within the httpd.conf file instead of the .htaccess file if you so wish. My preference is to use the .htaccess file as it’s more portable, and generally easier to edit.

After you’ve edited the httpd.conf file / contacted your server guys or whatever – you should be good to go. If not, I’m all out of ideas. Sorry. Try Google for help :].

Assuming all’s working well, let’s get to the cool bits!

Masking Pages with Mod_Rewrite

This is kind of pointless, but is a simple demonstration for this tutorial. If you don’t care much for pointless, simple-to-understand demonstrations, go straight to the useful rewrite rules.

First create two basic HTML pages. Name them ‘page_one.htm‘ and ‘page_two.htm‘. Add a little dummy content to both of them, but make sure they have different content (this is so as we can differentiate the pages). Open your .htaccess file, and if you don’t have the main opening lines:

Options +FollowSymLinks
Options +Indexes
RewriteEngine On

Add them now. On the next free line, add the following:

RewriteRule ^page_one.htm$ page_two.htm [L]

Now, load page one. What do you see? Page two hopefully. How? Well, the RewriteRule breaks down like this:

RewriteRule [FIND THIS] [REPLACE WITH THIS] [FLAGS]

RewriteRules have 4 main parts to them. The rewrite action:

RewriteRule

Then the FIND THIS part:

^page_one.htm$

This is a regular expression. Everything found in between the circumflex (^) and dollar sign ($) will be searched for and saved as a variable (more on this later). If the FIND THIS value is found, it’ll be replaced with the third part of the RewriteRule – the REPLACE WITH THIS:

page_two.htm

The fourth and final part of the RewriteRule is the flags. You can put flags in between square brackets ([ ]) to control how mod_rewrite should deal with the rule itself.

[L]

I’ve simply used one flag, ‘L’. This means that this is the last rule. As we only have one rule at the moment, using this flag seems appropriate, as it’s the only, and last, rule. You can use multiple flags, by comma delimiting them. There is a list of the flags at the end of this tutorial.

Rewriting Dynamic URLs

Let’s take the first URL mentioned in this tutorial as the example for this part of the tutorial:

http://domain.com/product.php?product_id=19

Create a new PHP page called product.php. Add the following code between the tags:

You are viewing product <?php echo $_REQUEST['product_id']; ?>

Save, and upload your file. You can view my example of product.php to see how the page changes with the dynamic content from the GET request.

Let’s say you would prefer to use a cleaner URL, such as:

http://domain.com/product/19/

This could be achieved by adding the following line to your .htaccess file:

RewriteRule ^product/([0-9]+)/$ product.php?product_id=$1 [NC,L]

You can test this in action if you wish. If we break down the RewritRule into the four parts again, you should be able to see how it’s working:

RewriteRule

Here, we’re simply stating that we’re adding a new rule for mod_rewrite to use.

^product/([0-9]+)/$

As before, this is the FIND THIS value. We are looking for a string within the URL that contains product/[NUMERICAL VALUE]/ – that is, the word ‘product’, then a forward-slash (/), then a numerical value only, then a final forward slash. The magic here lies between the brackets ( ):

([0-9]+)

The brackets ( ) are telling mod_rewrite to store whatever it finds within the brackets in a variable. The [0-9]+ is a simple regular expression allowing only numbers 0 to 9, and the + sign means ‘any number of’. So we can have 99 or 123 for example, not just one number, such as a 9 or a 1.

we finally add a trailing slash (/) at the end to finish what we’re looking for (as our desired clean URL is product/[PRODUCT ID]/).

product.php?product_id=$1

The third part of our RewriteRule is the REPLACE WITH THIS part. Here you can see the actual page name, with the query string – but this time there’s something new. Where we used to have the product ID, we now have a variable $1. $1 will contain the value of the result of the regular expression found within the brackets in the FIND THIS part. Can you see it all falling into place now?

[NC,L]

Finally come the flags. I’ve used two flags here, NC meaning that the rule is case insensitive (it just protects us incase anyone uses http://domain.com/Product/19/ for example), and L meaning it’s our last rule.

Feel free to check this out with a working example. Change the number from 19 to a different number and see what happens.

Mod_Rewrite Flags

  • C – Chain
  • E – Environmental Variable
  • F – Forbidden
  • G – 410 Gone
  • L – Last
  • N – Next (Round)
  • NC – No Case
  • NE – No Escape
  • NS – No SubRequest
  • P – Proxy
  • PT – Pass Through
  • QSA – Query String Append
  • R – Redirect
  • S – Skip
  • T – Type

Closure

I could go on and on with more examples of mod_rewrite, but that would exceed the scope of this tutorial – seeing as this is only a beginner’s tutorial. Through this tutorial, I hope that you’ve learned enough of the basics in order to get you started. You should now know:

  • How to get mod_rewrite working.
  • How to mask pages.
  • How to create cleaner URLs for dynamic pages.

Useful Reading & References


Categories: .htaccess, Apache


41 Responses so far.


  1. James says:

    I followed your example excatley, however it just doesnt work. Ive been trying for a couple of hours to get any SEO friendly .htaccess scripts to work.

    I know rewrite is enable, as i can do a simple x.php to b.html easy enough.

    But for some reason your code just does nothing? Any ideas?

    Many thanks in advance

    • IBOAM says:

      i had the same problem but i was appache settings now i tried on my domain an it works fine thanks to this tutorial

  2. Ed says:

    Hi James,

    Could you post your .htaccess script and related .php file code? Alternately send them to me and I’ll happily look at them for you.

    Cheers!

  3. fx says:

    Aloha.. thx for that tutorial..
    For some reasons this wont work for my site :S

    i tried following:

    RewriteRule ^clip/([0-9]+)/$ index.php?action=goto&url=$1 [NC,L]

    Pleez help

  4. Ed says:

    Hi FX,

    Did you do the Testing Mod_Rewrite Works section, and can confirm that it works ok? If so could you send me your full .htaccess file, and point me to where you’re hosting it?

    Use the contact me link at the top of this site to send me any files for checking.

    :)

  5. c0de says:

    Hey,

    This is great, thanks for the post.

    Just wanted to confirm that it works for me, I’ve noticed that some people have said they’re having problems. Make sure that you have mod_rewrite installed, and go through the Testing part of this tutorial to check it all works.

    c0de.

  6. sukesh says:

    Your tutorial was helpful! I have one question on url masking

    I would like to restrict the url displayed in the address bar of the browser to main page say http://www.mysite.com/welcome

    now even if user moves to another link say page2 I want the display to stick to http://www.mysite.com/welcome instead of
    http://www.mysite.com/welcome/page2

    I would appreciate if you could give me some pointers or share an example code demonstrating how this can be done.

  7. Ed says:

    Hi Sukesh,

    I have added a live demo of the URL masking guide at:

    http://www.edrackham.com/tutorials/beginners_mod_rewrite_tutorial/test/page_one.htm

    Is this what you’re looking for? It’s using the same code in the URL masking section of this tutorial. When you load the above link, you will see page two, but the URL remains as page one.

  8. Raimis says:

    Dear Ed,

    maybe you know where to find information how to step by step make ssl server from Apache side and PHP.

  9. dehiv says:

    Hi Ed, I have a question, i see that the rule works fine:

    RewriteRule ^product/([0-9]+)/$ product.php?product_id=$1 [NC,L]

    but what happen if i add the flag R=301?:

    RewriteRule ^product/([0-9]+)/$ product.php?product_id=$1 [R=301,NC,L]

  10. Ed says:

    Hi dehiv,

    If you use the redirect flag (R), make sure you use a fully qualified URI for the REPLACE WITH THIS part of the RewriteRule, i.e:

    RewriteRule ^product/([0-9]+)/$ http://www.domain.com/product.php?product_id=$1 [R=301,NC,L]

    Otherwise, mod rewrite will insert the document root (something like /var/www/sitename/public_html/page.php) which will fail.

    The other thing to note is that the URI will be updated to reflect the new URI, as a 301 HTTP request is a permanent redirect.

    Ed.

  11. dehiv says:

    @Ed: thank’s for the help, then i understand that the correct way to use clean urls is not add the redirect flag in this case. If i use it, i’ll loose the clean urls because of the redirection.

    dehiv

  12. Foster says:

    I followed your example excatley, however it just doesnt work. Ive been trying for a couple of hours to get any SEO friendly .htaccess scripts to work.

    I know rewrite is enable, as i can do a simple x.php to b.html easy enough.

    But for some reason your code just does nothing? Any ideas?

    Here is my .htaccess script
    Options +FollowSymLinks
    Options +Indexes
    RewriteEngine On
    RewriteRule ^shingletown/([0-9]+)/$ Shingletown_Articles.php?article_shingletown=$1 [L]

    AND here is the Link
    http://ridgeridernewsshingletown.com/Shingletown_Articles.php?article_shingletown=53

    Any Help would be GREAT!

  13. Danny says:

    Hi Thanks, but it doesn’t work for m.

    I dont use only ([0-9]+) number values, but also string for example

    I want to load http://www.domain.com/agenda/kind/Bar/

    Options +FollowSymLinks
    RewriteEngine on
    RewriteRule agendaget/(.*)/(.*)/$ /agenda.php?$1=$2 [NC,L]

    It load agenda.php without any values.

  14. Farhan says:

    Great Job..
    I searched a lot of tutorials for mod_rewrite, but your tutorial is superb.
    Thank you for this great tutorial.
    keep it up..

  15. stereotyped says:

    nice man.
    it really help alot.
    *two thumbs up!

  16. dan says:

    Thanks a lot for this great tutorial, was looking for something nice and simple and to explain exactly how mod_rewrite works. Found it ;) Just wondering if you could provide more detail/explanation on what all the flags do. Thanks again

  17. [...] View Tutorial No Comment var addthis_pub=”izwan00″; BOOKMARK This entry was posted on Friday, June 5th, 2009 at 8:22 am and is filed under Php Tutorials. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site. [...]

  18. Mark says:

    Awesome tutorial!
    I have a quick question:

    How do I append say a category name on to the end of a ‘modded’ url if the original dynamic one never had it?


    RewriteRule ^category/([0-9]+)/?$ results.php?cat_id=$1 [NC,L]
    RewriteRule ^detail/([0-9]+)/?$ detail.php?cust_id=$1 [NC,L]

    I have dynamic loaded category names I can append in the html. What I want to achieve is:

    mydomain/category/20category-name.html OR …./20/category-name.html

    AND
    mydomain/detail/50customer-name.html

    Thanks again!!!

  19. Mark says:

    I hope I was clear.
    I want to rewrite my url to this:
    mydomain.com/category/50/metal-widgets.html

    starting from this:
    mydomain.com/results.php?cat_id=50

  20. Ed says:

    Hey Mark,

    You could use:

    RewriteRule ^category/([0-9]+)/([A-z0-9-]+).html$ results.php?cat_id=$1 [NC,L]

    Your code that generates the page with the links such as:

    mydomain.com/category/50/metal-widgets.html

    Would need to dynamically insert the page-name.html part itself, as this has no real bearing on the mod_rewrite rule – the /50/ part does all the leg work.

    I hope that makes sense?

  21. Mark says:

    Thanks for the response Ed!
    I believe I have done the same thing with a wildcard. Here’s what I used and it seems to work:

    RewriteRule ^category/([0-9]+)([^"]*)/?$ results.php?cat_id=$1 [NC,L]

    I didn’t use the forward slash in theiddle as you did but I think the wildcard took care of it. I had to put leading and trailing slashes into my rewritten urls but all works! Thanks again for an easy to digest and learn tutorial!

  22. Chris Beck says:

    Not bad… this tutorial provides a few other cool features:

    http://www.openzu.com/Tips-&-Tricks/Apache-Mod-Rewrite/p-44/

  23. Sa says:

    Hi Ed,

    My current rewrite page has css and other files in it(from other folders like ../css/style.css ). When i redirect current page, those are not working.
    How to write rewrite rule to get css files on current page.

  24. venkat says:

    i use mod_rewrite like this:
    RewriteRule ^view/([0-9]+)/$ view.php?id=$1 [NC,L]

    but it is not working.
    Tell me the problem.

    Thanking you for answering me.

  25. mark says:

    Thanks for the tutorial. I had a quick go and i managed to get your example working. I just tried to get one of mine to work without any luck.
    my file is clients/viewClient.php?ID=1 and my htaccess is

    RewriteRule ^viewClient/([0-9]+)/$ viewClient.php?ID=$1 [NC,L]

    That is my line. But i have it in a clients folder. I tried to move the .htacces file into the clients folder but that doesn’t work either. Very new at this and i cant seem to get anything working. Any help would be great thanks.

  26. Check projektowanie stron
    This is the greatest seo firm i seen. They are good with yahoo and other kinds of whitehat tactics.
    I can say they really rule with companies.

  27. Along with thank you for this excellent content material, I will probably attach this web site in order to my very own rss feeds, a buddy basically educated me personally with this two to three weeks back. here is the finest

  28. [...] have written a mod_rewrite tutorial, but this is worth a mention as a top 10 tip for .htaccess files as it’s becoming more and [...]

  29. bobkomas says:

    I love music like “Queen”. What about you?

  30. macrunning says:

    tried this and can’t get it to work. Would love a solution. I see several others have had a problem as well. I have tested basic rewrite and it works switching service.php to parts.php. I am positive the Rewrite engine is on. I also copy and pasted your example to avoid any errors and still can not get this darn thing to work with the dynamic url. Any ideas?

  31. Ed says:

    Hi macrunning,

    Can you provide your non-dynamic URL, i.e.:

    http://example.com/page/dynamic.php?id=123

    and the rewrite directive that you’re using? I.e.:

    RewriteRule ^page/([0-9]+)/?$ page.php?id=$1 [NC,L]

    I’ll endeavor to help you get this working :)

    Thanks,

    Ed.

  32. macrunning says:

    Hi Ed,
    I wish I saved it. I got so fed up after working on this for several hours I deleted the .htaccess file I was working on. Below is the current .htaccess file that is working but does not contain any re_write in terms of transforming ugly urls to seo friendly urls.:
    RewriteEngine on

    IndexIgnore .htaccess */.??* *~ *# */HEADER* */README* */_vti*

    order deny,allow
    deny from all
    allow from all

    order deny,allow
    deny from all

    AuthName dodgeoftulsa.com
    AuthUserFile /home/dodgeoft/public_html/_vti_pvt/service.pwd
    AuthGroupFile /home/dodgeoft/public_html/_vti_pvt/service.grp
    RewriteCond %{HTTP_HOST} ^dodgeoftulsa.com$
    RewriteRule ^(.*)$ http://www.dodgeoftulsa.com/$1 [R=301,L]

  33. Dotiv says:

    nice tutorial…
    but please tell me if you know. how can i use this without mod_rewrite…

  34. Mary Sharpe says:

    Well, I don’t know in the event that’s going to work with me, but definitely worked for you personally! Excellent post! This is really my first time here, great looking blog. I discovered a lot of interesting things inside your blog especially its discussion. From all the remarks on your articles, it appears such as this is really a very popular website. Continue the great work.

  35. Thanks for your entire efforts on this blog. Kim really loves working on investigations and it’s simple to grasp why. My partner and i hear all relating to the powerful form you provide useful tactics via the web blog and as well boost participation from some others on the point so my girl is always becoming educated a lot. Take pleasure in the rest of the new year. You are performing a first class job.

  36. azzax says:

    Hello, I would want to know as how to implement something like

    http://example.com/username

    somewhat similar to twitter.com/azzaxp

    where each user name is taken from $username…

    right now i have been using http://example.com/profile.php?id=1

    So want it to be masked as above…

    Please do write to me at azzaxp@gmail.com

  37. Archibald says:

    Maybe you have deemed including additional videos to your websites to help keep your readers additional entertained? I mean I just read through the entire article of yours and it was very fine but as I’m really a visual learner,I discovered that being more helpful. Just my my idea, Good luck

  38. Suman Rai says:

    Hi,
    Thanks for your excellent help. Anyways, i have following conditions

    RewriteRule ^article/([0-9]+)/([a-z]+)$ article.php?id=$1&title=$2 [L]

    the rule works fine but the CSS and Image files are not working.

    All the css design not working on http://localhost/article/1/title

    how to fix this error,

    And also, please help me, I have linked on index.php file as following :

    <a href="article//Artifcle

    is this correct way to link or is there any dynamic technique

    Hope you understand and reply me soon.
    Thanks,

Leave a Reply