23

CodeIgniter htaccess

CodeIgniter

This is the CI .htaccess file that I use for my CodeIgniter PHP projects (some of these CodeIgniter htaccess rules can be used for any project, keep reading). CodeIgniter uses mod_rewrite to route all requests to the CI front controller. I’ve made some additions in an attempt to canocalize some of the CodeIgniter URL end points. The key benefit of a canocalized URL is that your search engine page ranking (page juice) is not spread across several pages, but instead, targeted to a single page.

htaccess Rule Breakdown

In your CodeIgniter project you will typically have a default controller and you will be able to access this controller at the following URLs:

/
/welcome
/welcome/
/welcome/index
/welcome/index/
/index.php

That’s a total of 6 URL end points pointing to the front controller. Additionally other controllers you’ve created will also have a default “index” method, consider the following:

/category
/category/index
/category/index/

Again, a total of 3 URL end points where there should only be one. The first set of rules in the .htaccess file prevent this:

# If your default controller is something other than
# "welcome" you should probably change this
RewriteRule ^(welcome(/index)?|index(\.php)?)/?$ / [L,R=301]
RewriteRule ^(.*)/index/?$ $1 [L,R=301]
 
# Removes trailing slashes (prevents SEO duplicate content issues)
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ $1 [L,R=301]

With these rules the front controller will always be accessed at “/” and any other URLs pointing to a controller’s “index” method will be accessed at “/controller”. Notice that I also use a 301 redirect, this aids in maintaining or passing any existing search engine ranking (page juice) to the final redirected page.

So these:

/welcome
/welcome/
/welcome/index
/welcome/index/
/index.php

… would simple become:

/

… and:

/category
/category/index
/category/index/

… would become:

/category

Another important thing to note: for controllers with an “index” method which take any sort of parameter, these URLs will still work as such:

/welcome/index/123
/category/index/123

To be able to remove the “index” (or “welcome/index”) and still have parameters passed in, you will need to configure your routes file.

The next set of rules allow you to enforce “www” or enforce NO “www”, you will have to pick which you prefer and enable one or the other. Additionally, for those who may have subdomains, adding the subdomains to the list (if enforcing www) will safely exclude those subdomains from being redirected.

# Enforce www
# If you have subdomains, you can add them to 
# the list using the "|" (OR) regex operator
RewriteCond %{HTTP_HOST} !^(www|subdomain) [NC]
RewriteRule ^(.*)$ http://www.domain.tld/$1 [L,R=301]
 
# Enforce NO www
#RewriteCond %{HTTP_HOST} ^www [NC]
#RewriteRule ^(.*)$ http://domain.tld/$1 [L,R=301]

The Full CodeIgniter htaccess File

Here is the entire .htaccess file that I use for my CodeIgniter projects. Remember that some of these rules are commented out, you will have to explicitly enabled them by removing the comments (removing the “#” from in front of the rule).

<IfModule mod_rewrite.c>
 
    RewriteEngine On
    RewriteBase /
 
    ### Canonicalize codeigniter URLs
 
    # If your default controller is something other than
    # "welcome" you should probably change this
    RewriteRule ^(welcome(/index)?|index(\.php)?)/?$ / [L,R=301]
    RewriteRule ^(.*)/index/?$ $1 [L,R=301]
 
    # Removes trailing slashes (prevents SEO duplicate content issues)
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.+)/$ $1 [L,R=301]
 
    # Enforce www
    # If you have subdomains, you can add them to 
    # the list using the "|" (OR) regex operator
    RewriteCond %{HTTP_HOST} !^(www|subdomain) [NC]
    RewriteRule ^(.*)$ http://www.domain.tld/$1 [L,R=301]
 
    # Enforce NO www
    #RewriteCond %{HTTP_HOST} ^www [NC]
    #RewriteRule ^(.*)$ http://domain.tld/$1 [L,R=301]
 
    ###
 
    # Removes access to the system folder by users.
    # Additionally this will allow you to create a System.php controller,
    # previously this would not have been possible.
    # 'system' can be replaced if you have renamed your system folder.
    RewriteCond %{REQUEST_URI} ^system.*
    RewriteRule ^(.*)$ /index.php/$1 [L]
 
    # Checks to see if the user is attempting to access a valid file,
    # such as an image or css document, if this isn't true it sends the
    # request to index.php
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ index.php/$1 [L]
 
</IfModule>
 
<IfModule !mod_rewrite.c>
 
    # Without mod_rewrite, route 404's to the front controller
    ErrorDocument 404 /index.php
 
</IfModule>

Apply These Final Touches to Clean Up the URL

Remember, once you have your CodeIgniter htaccess file setup, you will want to go into your “/system/application/config/config.php”, find the following:

$config['index_page'] = "index.php";

and change it to:

$config['index_page'] = "";

Because you are using Apache mod_rewrite, the above will set your config file so that “index.php” will NOT show up as part of the URL as such:

http://www.example.com/index.php/controller/method/variable

instead your URLs will be cleaner:

http://www.example.com/controller/method/variable

If you have comments or improvement suggestions please let me know.

Related posts

  1. CodeIgniter NGINX Rewrite Rules
  2. CodeIgniter Form Validation — Conditional Required Field

{ 23 comments… read them below or add one }

Kyle June 6, 2009 at 8:04 am

Really helpful, thanks.

juandelacruz July 7, 2009 at 8:39 am

Nice. This is something to try on…

Jeremy Blake August 8, 2009 at 8:17 pm

Dude, most of your blog posts are way over my head. I need to read your blog more. I might learn something important! Keep it up.

marcello September 9, 2009 at 10:47 am

hi, you forgot /index.php/welcome is the same as / , but your solution doesn’t redirect it.

can you provide some solution for this to be complete?
I tried RewriteRule index\.php/(.*)$ $1 [L,R=301] (doesn’t work well)

it works with /index.php/welcome, but there’s an infinite loop in things that doesn’t work, so it’s definitely not a good solution. Thank you

Dimas September 9, 2009 at 6:11 pm

marcello, since you are using mod_rewrite, make sure you set your config file so that index.php will NOT show up as part of the URL:

$config['index_page'] = “”;

setting this option to an empty value should do the trick.

David September 20, 2009 at 3:38 pm

If you want to force trailing slashes then you can use this rule instead.

# Forces trailing slashes (prevents SEO duplicate content issues)
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !/$
RewriteRule ^(.+)$ $1/ [L,R=301]

Dimas December 14, 2009 at 10:22 am

David, thank you for your contribution … I will add your lines to the post above, with a slight caution …

For those using trailing slashes with the above rewrite rule: be aware that when using the CodeIgniter “site_url(path)” method and other methods which depend on it (like “form_open(‘path’)”) … CodeIgniter will automatically remove trailing slashes by default, this seems to be hard-coded into the “libraries/Config.php” file (obviously if you need to get around this you can extend and change class to fit your needs).

Symptoms of the above: would be URLs that always get redirected (no big deal) and in regards to the “form_open()” method, the form submission would get redirected by the rewrite rule causing form data to be lost during the redirect.

Jaap December 23, 2009 at 1:18 am

Hi, Thank you for this useful post.
I implemented the .htacces file at one of my projects.

But there is still one problem I think.
It is still possible to request:
http://www.domain.tld/index.php/controller

Is there a way to remove the index.php?
Thanks in advance!

Jaap December 23, 2009 at 1:19 am

Sorry, I see the solution now, didnt read the comments ;)

Chuck Lidderdale January 3, 2010 at 11:17 am

An annoying dupe problem. On a shared host my htaccess file contains
RewriteCond %{HTTP_HOST} blackforest-co.com
RewriteCond %{REQUEST_URI} !/blackforest/
RewriteRule ^(.*)$ /blackforest/$1 [L]

that works fine – except when one clicks on a link it comes back as:
http://www.blackforest-co.com/blackforest/bfcc/ when it should be (which works)
http://www.blackforest-co.com/bfcc/

Just doesn’t look … clean. Any fix? Thanks

Ra January 5, 2010 at 6:28 am

Really nice tutorial to keep in your bookmarks. Best about htaccess I have yet seen.

Tzvook January 11, 2010 at 7:41 am

Hi
.htacsess us still voodo to me :-(
I got panalized by google fot this one:
—————————
Options +FollowSymLinks
rewriteEngine on
# Internally rewrite .my-domain.tv/ to my-domain.tv/pages//
rewriteCond $1 !^pages/
rewriteCond %{HTTP_HOST} !^www\.my-domain\.tv
rewriteCond %{HTTP_HOST} ^([^.]+)\.my-domain\.tv
rewriteRule (.*) /pages/%1/$1
————————————
Do you see any reason for it in here ?

Dimas January 11, 2010 at 8:34 am

Tzvook, to be honest i’m still a noob SEOer … your rules look interesting, looks like your taking your subdomains (anything other than www) and putting them at /pages/subdomain/path/to/file … the only thing i could think of is to make sure that you do not have any URLs going to the same content and to maybe slap a [L,R=301] at the end of the rule telling search engines that the page has permanently moved. From me readings this helps google update its index.

Tzvook January 11, 2010 at 12:14 pm

10X Dimas

azifet January 24, 2010 at 10:23 am

Nice post there… however form data in the post variable $_POST gets lost whenever I redirect to the bootstrap file. any idea on how to work around this?

Dimas January 24, 2010 at 8:29 pm

azifet, If the redirects work as expected, make sure that the form data is being submitted to the final end point URL, not a URL which will cause a redirect adjustment (causing the lose of form data).

Also note that by default CodeIgniter does not like trailing slashes, some methods within CodeIgniter will remove trailing slashes, also causing lose of form data.

alex February 22, 2010 at 4:38 pm

tx for sharing this. I am using it for my first CI project which also holds a Wordpress subfolder. So i can get some wp-posts in CI views.
p
But the default page url doesn’t work mydomain.com/?p=123
should i edit the .htaccess.

any suggestions,
regards
ps i have wp in /blog and in the end i like to have something blog/%custom%

Dimas February 22, 2010 at 5:59 pm

Alex, I’ve actually recently put together a similar setup to yours on my Blogging Topics site.

http://www.bloggingtoc.com/ (CI site)
http://www.bloggingtoc.com/blog/ (WordPress site)

The setup was easy, i’m using the same .htaccess file as above (modified with the correct url/subdomains for my site) … after setup everything worked “out-of-the-box”.

You will have to go into WordPress > Settings > Permalinks … and set Custom Structure to “/%postname%/”.

Here is an example:
http://www.bloggingtoc.com/blog/hello-world/

alex February 25, 2010 at 12:51 am

Hi Dimas,

I think i am going to have a problem with CI + WP and SEO url’s/permalink, see my topic on http://codeigniter.com/forums/viewthread/147068/

How would you bypass /blog/ and have the url request go to CI or WP???
Hope i am making sence

regards

pit March 26, 2010 at 4:42 pm

it works perfectly … comments are simple but very helpful … great job in fact!

thanks!

Asif Iqbal June 23, 2010 at 1:12 pm

Hi,

Nice post.. I am new in the Codeigniter and this post really helpful for me.

Thanks mate.

zeratool July 22, 2010 at 10:20 pm

You can simplify that to this:
#begin
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [QSA,L]
#end
HTH

Dimas July 22, 2010 at 10:33 pm

That would definitely work too!

Leave a Comment

You can use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>
<pre lang="" line="" escaped="">

Previous post:

Next post: