Create Beautiful URLs With mod_rewrite
You’ve got your website up, custom-built and it looks amazing. Except, of course, for that URL. You’ve heard of mod_rewrite
, but the idea seems confusing and scary – I mean, regular expressions; hell.
It’s actually a lot easier than you might think. mod_rewrite
is an incredibly powerful tool and can do some pretty advanced stuff; however, when you’re only looking to beautify your URL, the process is quite simple.
mod_rewrite
uses a file in the root of your site called .htaccess
– all your mod_rewrite conditions will go into this file. If it doesn’t already exist in your site files, create it.
Let’s take the following URL for example:
www.example.com/index.php?page=news&story=123
Great – you have the page pulling up the right story, it all looks wonderful – but that URL is ugly and won’t help you in your Google rankings.
So, let’s open our .htaccess
file and do some magic:
Options +FollowSymlinks
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_URI} ^/news
RewriteRule ^news/([0-9]+)/?$ index.php?page=news&story=$1 [NC,NE,L]
That’s it!
So, what does it all mean?
Options +FollowSymlinks
This option allows your rules to use and follow symbolic (shortcut) links within your directive. For example, you could have multiple sub-domains within your system, and you want them to all use the same uploads folder – you create the one folder and create a symbolic link to that folder within each sub-domain.
It’s likely that this option is unnecessary for you, but add it if you know there will be symbolic links – it won’t affect your rules if symbolic links don’t exist.
RewriteEngine on
This just turns the mod_rewrite
engine on. Without this, none of your rules will work.
RewriteBase /
This part isn’t really necessary if all your rules use absolute paths; but absolute paths make rules less portable, so it’s best to use RewriteBase
to allow you to write with relative path urls, that way when you want to port a rule to another site, you only have to change the RewriteBase
and not all your rules. There’s a lot that goes with this RewriteBase
, and I won’t get into all the details here, but if you want all your rules to happen from the root of your URL (i.e. example.com/
instead of example.com/this-is-where/i-am/123
) then just include that line as I show above. To get more information on this, go to the Apache mod_rewrite site.
RewriteCond %{REQUEST_URI} ^/news
It’s likely that you’ll have more than just one rewrite in your .htaccess
file, so it’s good to use things called RewriteCond
– these conditions allow you to make sure that the URL that’s being rewritten actually meets the requirements; otherwise, you’ll have some weird behavior from your rules. This particular condition ensures that the first piece of the URL contains news
– pay close attention to the ^
at the beginning – this is important because it ensures we are looking at the URL from the start; ^
means “starts with”.
RewriteRule ^news/([0-9]+)/?$ index.php?page=news&story=$1 [NC,NE,L]
This is the meat of the actual rewrite – we’ve met all our conditions, and now let’s actually do something with this URL. Let’s dissect this URL piece by piece:
^
– “starts with” – same as above.
([0-9]+)
– this is where regular expressions come in handy.
()
– the brackets enclose an entire string of text, so we know we’re looking for a string that fits the enclosed regular expression.[0-9]
– We are looking for a number.+
– this means “one or more”. So, we know that you’re looking for a number, but we don’t care how long that number is (i.e.123
v.s.123456789
) – this will also mean that it won’t rewrite a URL that doesn’t have a number – meaning the main page for news wouldn’t try and rewrite into a story page.
/?
– this part is particularly important, because sometimes a URL can have a trailing slash – but not always. We want to catch both cases and make sure to supply what we’re looking for. It’s important to note that it’s best practice to write rules that actually remove (or add) trailing slashes to your URLs – pick one or the other – you can run into duplicate content issues if you have links to the same page, some with the trailing slash, some without. For the sake of this example though, we’re going to account for both situations.
$
– just means “end of string”.
index.php?page=news&story=$1
– here’s the URL that we’re wanting the page to actually display when it sees our pretty URL. The brackets we were discussing above, they enclose a string – anytime you enclose a string in your regular expression, the rewrite can pass that string to your end URL. So, since we have our string enclosed in our expression, we use $1
to have the rewrite push that part out to our new URL. If we had 2 enclosed strings in our regular expression, they would be $1
and $2
respectively.
[NC,NE,L]
– these are our flags. There are a ton of tags you can use, but for this example we’ve used the following:
NE
– Do not escape outputNC
– We want this rule to be case-insensitiveL
– This is our last rule for this URL – stop processing if this rule matches.
You’re done! Now you have beautiful URLs and it really wasn’t that difficult! This particular example used a numerical value for the story URL variable because often that’s where developers will start, because it makes it easier to grab things from a database; however, I would highly recommend using a URL-friendly version of the story title instead of the ID. This will increase your SEO and is also a lot prettier.