0

So it seems I can find solutions for some of these but can't get them to all work together. What I am trying to do is create clean URLS from all sides.

  1. resolve all www. and non-www. to the non www. page
  2. remove all occurrences of index.php (i.e. if navigating to folder /blog/index.php resolve as /blog/)
  3. remove php extension from all URLS (i.e. /page.php to /page/)
  4. add trailing slash (i.e. /page to /page/)

This is what I have so far:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .*[^/]$ %{REQUEST_URI}/ [L,R=301]
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+)/$ $1.php [L]

This accomplishes the clean URL's removing the .php extension and adding the trailing slash. I had to take out the www.to non and removal of index.php because the clean urls and trailing slashes stopped working. Thank you all in advance.

1
  • You sure the URLs will still work like that? It seems like you want to redirect the user from ../page.php to ../page/, but will Apache know where to look for ../page/? Commented Oct 20, 2014 at 22:44

1 Answer 1

2

Here's what your .htaccess should look like:

RewriteEngine On

# Remove www.
<IfModule mod_rewrite.c>
    RewriteCond %{HTTPS} !=on
    RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
    RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]
</IfModule>

# Remove file extensions, add a trailing slash.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]+)/$ $1.php
RewriteRule ^([^/]+)/([^/]+)/$ /$1/$2.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/)$
RewriteRule (.*)$ /$1/ [R=301,L]

This is a really good reference article about removing file extensions fro URLs. Just remember, for this to work, you must reference the non-extension version in all of your links e.g. <a href="about">About</a>, not <a href="about.php">About</a>

While you're doing .htaccess things, I might also recommend adding in the following snippets. The first two are concerned with website speed, the second is for a custom 404 page, and the third is for forcing UTF-8 (so you don't have to declare it in your HTML).

# Expires caching (Caching static files for longer drastically improves performance, you might even want to put even more aggressive times)
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access 1 year"
ExpiresByType image/jpeg "access 1 year"
ExpiresByType image/gif "access 1 year"
ExpiresByType image/png "access 1 year"
ExpiresByType text/css "access 1 month"
ExpiresByType text/html "access 1 month"
ExpiresByType text/x-javascript "access 1 month"
ExpiresByType image/x-icon "access 1 year"
ExpiresDefault "access 1 month"
</IfModule>

# Gzip 
<ifmodule mod_deflate.c>
AddOutputFilterByType DEFLATE text/text text/html text/plain text/xml text/css application/x-javascript application/javascript
</ifmodule>

# 404 Page
ErrorDocument 404 /404.php

# Force UTF-8
AddDefaultCharset utf-8

I wrote about this in a blog post on CodePen, if you're interested.

HTML BP has an insane 700+ line .htaccess that you can see for some cool tricks.

Sign up to request clarification or add additional context in comments.

5 Comments

Why is part in a IfModule and part isn't?
I guess you could put it all in and IfModule, I just didn't.
The reason that that part of it is in an IfModule is because I took that part from HTML BP (which has everything in IfModules) and I wrote the other part. And I just never changed it, I've used the same .htaccess for forever.
This works great thank you, it does also let you go to the .php version of the page although I can use canonical to fix that. I assume thats the best way?
Yes, for SEO reasons providing the canonical meta tag is always a good idea and the .php version will always be there as that's the name of the actual file (and not allowing people to access the .php version doesn't make much sense. Besides, it's the convention to allow both, look at www.facebook.com/index.php and www.facebook.com). You just need to link to the non .php version e.g. "about.php" -> "about" if that's what you want to use.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.