Pretty urls (remove file extension, fake folders)

Everything related to the visual and coding aspects of websites.
Masao
Host
Posts: 579
Joined: Thu Jun 16, 2011 12:29 am
Contact:

Pretty urls (remove file extension, fake folders)

Post by Masao »

Not sure how many people would find this useful, but I've done this myself, but had issues with it messing up my sub folders, so I always avoided it for my main domain (since all my subdomains are really folders within my main domain).

An example of "pretty urls" is having:
really direct to:
A lot of CMS scripts (like wordpress) will do this, and it's done through Mod_Rewrite in a .htaccess file. A few lines will do this, but the issue is it capturing actual folders/directories and incorrectly attempting to map them to a non-existing file.

Say you have:
but when you type it in the browser, you get a 404 error because your server tries to redirect it to:
Which of course doesn't exist.

To get around this, you have to exclude your rewrite rules on files and directories. The code I use in my .htaccess file:

Code: Select all

DirectoryIndex index.html index.php
RewriteEngine on

RewriteCond %{REQUEST_FILENAME} -f
RewriteRule .* - [L]

RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .* - [L]

RewriteRule ^([a-zA-Z]+)\/?$ $1.php
RewriteRule ^([a-zA-Z]+)\/([a-zA-Z]+)\/?$ $1.php?$2
The first line tells your server to default your directory index file to index.html, and if that doesn't exist, fall to index.php; most hosts have this already set up, so it's optional, but if you'd like to specify, you can (like make main.php the default).

The second line tells apache (the typical server most of us are using; .htaccess only works on apache servers) to start reading the subsequent lines as rules for rewriting.

Code: Select all

RewriteCond %{REQUEST_FILENAME} -f
RewriteRule .* - [L]
This part is saying if the requested url is a file (the -f flag), do the next line, which is a wildcard capture of any filename, and doing nothing with it. A period (.) is matching any characters, and the asterisk (*) is saying zero or more of the preceding token. The dash (-) after that means to do nothing, and the [L] flag at the end means last rule for this particular condition.

Code: Select all

RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .* - [L]
This is pretty much the same as above, except the -d flag means directories/folders.

Code: Select all

RewriteRule ^([a-zA-Z]+)\/?$ $1.php
RewriteRule ^([a-zA-Z]+)\/([a-zA-Z]+)\/?$ $1.php?$2
The last bit is the part that will give you the "pretty" urls. The first line captures any level one urls, like http://sub.domain.com/page and directs it to http://sub.domain.com/page.php (if you'd like it to redirect to another file type, change the .php at the end).

The ^ character indicates the start of your url pattern (regex), and the $ sign indicates the end, so all rewrite capturing patterns must follow that format. The characters between ^ and $ is the matching regex rule.

A "capturing group" is surrounded by parentheses ( and ), while the square brackets [ and ] surround your allowed character range. So for example the above line means any letters lowercase (a-z) or uppercase (A-Z). The + at the end means one or more of the preceding token. After that capturing group, the "\/" translates to just a "/" (the \ backslash escapes the / forward slash, you can just do a / forward slash, I only escape the character to be sure it's read as a forward slash just in case). The ? after the slashes means one or zero of the preceding token, so your pretty url will work with or without a / at the end.

A space follows that, then the matching file to redirect to. The "$1" means the first capturing group, and it will look for the first group with ( and ) around it and replace it with what you typed.

The second rewrite rule does the same thing, except it matches additional level files, so like page.php?name with the "$2" indicating the second capture group (the second group of letters it finds surrounded by parentheses).

If you want it to match a url of page.php?name=title then use this as the last line instead (modify it to match whichever form you like):

Code: Select all

RewriteRule ^([a-zA-Z]+)\/([a-zA-Z]+)\/?$ $1.php?name=$2
If you'd like to do level 3 urls:

Code: Select all

RewriteRule ^([a-zA-Z]+)\/([a-zA-Z]+)\/([a-zA-Z]+)\/?$ $1.php?cat=$2&page=$3
And if you'd like your pattern to match more than just letters, replace the [a-zA-Z] with [a-zA-Z0-9-] to get letters, numbers, and dashes.
THE FATE OF DESTRUCTION IS ALSO THE JOY OF REBIRTH.
Megan A
Posts: 480
Joined: Mon Feb 02, 2015 10:54 am

Re: Pretty urls (remove file extension, fake folders)

Post by Megan A »

Thanks for this, Masao! This is something I'd been wanting to do, and I'm excited to play around with it!
dubiousdisc
Administrator
Posts: 2535
Joined: Thu Jun 21, 2012 5:49 pm
Contact:

Re: Pretty urls (remove file extension, fake folders)

Post by dubiousdisc »

Thank you so much for this! I haven't been able to find a guide that didn't treat me like an idiot for not knowing this and I've been wondering about it for a while, so thank you so much!
Masao
Host
Posts: 579
Joined: Thu Jun 16, 2011 12:29 am
Contact:

Re: Pretty urls (remove file extension, fake folders)

Post by Masao »

Megan A wrote:Thanks for this, Masao! This is something I'd been wanting to do, and I'm excited to play around with it!
You're welcome! I hope you find it useful :heh:
dubiousdisc wrote:Thank you so much for this! I haven't been able to find a guide that didn't treat me like an idiot for not knowing this and I've been wondering about it for a while, so thank you so much!
No problem, I know that stuff can seem really confusing if you're already unfamiliar. When I figured out how to best make it work, I researched exactly why it worked as opposed to when I followed other tutorials that didn't, and it helps me a lot in understanding the different flags, like [L] for last rule.
THE FATE OF DESTRUCTION IS ALSO THE JOY OF REBIRTH.
Elysa
Posts: 161
Joined: Tue Jul 17, 2012 7:28 am

Re: Pretty urls (remove file extension, fake folders)

Post by Elysa »

I've always wondered how people did this, thanks for sharing, Masao!! :D
Masao
Host
Posts: 579
Joined: Thu Jun 16, 2011 12:29 am
Contact:

Re: Pretty urls (remove file extension, fake folders)

Post by Masao »

Elysa wrote:I've always wondered how people did this, thanks for sharing, Masao!! :D
No problem! I hope it's useful :heh:
THE FATE OF DESTRUCTION IS ALSO THE JOY OF REBIRTH.
Lysianthus
Posts: 23
Joined: Sun May 17, 2015 9:34 pm
Location: Philippines
Contact:

Re: Pretty urls (remove file extension, fake folders)

Post by Lysianthus »

Another trick I would suggest is to simply catch any character that is not a forward slash, instead of having to declare the characters manually (0-9a-zA-Z), so:

Code: Select all

RewriteRule ^([^/]+)/([^/]+)/([^/]+)/?$ $1.php?cat=$2&page=$3 [L]
The ^ means "not", so [^/] means "anything that is NOT /". :ok:
Affelius (creative) ☆ Asclaria (network) ☆ Lysianthus (personal)
Masao
Host
Posts: 579
Joined: Thu Jun 16, 2011 12:29 am
Contact:

Re: Pretty urls (remove file extension, fake folders)

Post by Masao »

Oh yes, that is a very good point. Catching all would be better for a "fits all" approach. I just personally like small whitelists over blacklists for paranoid security reasons.
THE FATE OF DESTRUCTION IS ALSO THE JOY OF REBIRTH.
Post Reply