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/\ [L,R=301] # Enforce NO www #RewriteCond %{HTTP_HOST} ^www [NC] #RewriteRule ^(.*)$ http://domain.tld/\ [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/\ [L,R=301] # Enforce NO www #RewriteCond %{HTTP_HOST} ^www [NC] #RewriteRule ^(.*)$ http://domain.tld/\ [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/\ [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/\ [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.
Really helpful, thanks.
Nice. This is something to try on…
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.
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
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.
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]
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.
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!
Sorry, I see the solution now, didnt read the comments 😉
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
Really nice tutorial to keep in your bookmarks. Best about htaccess I have yet seen.
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 ?
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.
10X Dimas
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?
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.
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%
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/
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
it works perfectly … comments are simple but very helpful … great job in fact!
thanks!
Hi,
Nice post.. I am new in the Codeigniter and this post really helpful for me.
Thanks mate.
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
That would definitely work too!
Dude! This definitely saved my life! Tks a lot!
Hi Dimas, thanks for the nicely documented .htaccess
We can learn a lot from documented code lines…
I’m setting up my first complex CI project. It will be hosted at my job (public health care) and it will powerup our intranet and webapps.
And now my question.
I set up a ci_sys, a ci_app, and a ci_www at the same level. Then I setup an alias pointing to the ci_www and making it my public folder.
# ci_app
# ci_sys
# ci_www
# # index.php
# # ci_assets
# # # css
# # # js
# # # img
So I basically set config file system_application to `../ci_sys` and aplication to `../ci_app`
With your .htaccess, I’m redirected one folder up in my alias
ex: base_url set to
http://myhost/myCI/
is redirected to
http://myhost/
Can you point me somewhere? Thanks
I host my website nibssolutions.
First time my site work well.
But this time it show many error.
Help me.
Very good, Thanks U
Pessoal, criei um site no Codeigniter e agora quero criar um blog vinculado a ele, ou seja, para ficar assim: http://www.meusite.com.br/blog. Alguém pode me dizer como posso fazer isso?
What you need to do is setup your blog (lets say WordPress), in the “/blog” subdirectory, you then need to adjust your rewrite rules. (I am also assuming that CodeInginter is installed in the root directory).
Try something like this in the CodeIgniter htaccess…
These are some really handy tips, thanks!
my url have duplicate
http://localhost/index.php/controller/function
http://localhost/controller/function
can anyone convert this to htaccess ?
$clean_url = str_replace(‘index.php’,”,current_url());
$current_url = ‘http://’.$_SERVER[‘HTTP_HOST’].$_SERVER[‘REQUEST_URI’];
if($clean_url!==$current_url)
{
redirect($clean_url,’location’,301);
}
Please write some posts about , how to setup Smarty 3 with CI ..
I didn’t really learn anything from this but wanted to. I would have liked it if you had explained the code more. For example what does:
RewriteRule (welcome(/index)? mean? What does the ? mean here? Does the (/index) imply what?
I’m getting some crawl errors in Google which point to a page that does not exisit on my website:
http://www.example.com/?p=123
What Rewritecond (or Redirect) script can I add to my .htaccess to redirect this to my homepage?
Thanks
Tom
i’m not pro but it seems that something like this should work (untested) :
RewriteRule ^\?p=[0-9]+$ / [L,R=301]
reads :
starting with
the string “?p=” once
followed with one or more Numeric character (between 0-9)
that is last character
then redirect 301 to home
Not sure about the starting character, if it does not work, try
RewriteRule ^p=[0-9]+$ / [L,R=301]
Or
RewriteRule ^.*\?p=[0-9]+$ / [L,R=301]
hope it can help ^^
I tried each one but they all result in the message “Nothing found for ?p=168”
Thanks for trying anyway
Tom
finally after some “live” testing and googling for help here’s the code that works for me 🙂
RewriteEngine on
RewriteBase /
RewriteCond %{QUERY_STRING} ^p=[0-9]+$
RewriteRule ^(.*)$ ? [R=301,L]
##OR: RewriteRule ^(.*)$ index.php? [R=301,L]
##where you can replace index.php with the landing page you want
Hope this time it’ll work as you need ^^
That’s great, you’ve cracked it! Thanks & well done
Tom
hi,
First i want to say that this is the best ever topic about CI url routes and mod_rewrite.
i have a question for my urls, they are like:
http://example.com/%5Busername%5D wich is working
now this isnt working (im useing “alternative to get” for ci)
http://example.com/home/var1:value1/var2:value2
however this is working when:
http://example.com/home/index/var1:value1/var2:value2
is there away to remove the /index/ from my “alternative to get” urls?
I have it all working for my /index.php/ and controller/index
its working like controller/ wich i find usefull!
Your explanation of how rewrite works was great and I can successfully implement it. However I loose my style sheet. This is the error I get:
[client 127.0.0.1] client denied by server configuration:
Anyone have any clues??
@Derk, you might have to play around with the routes file.
@Dennis, htaccess rules always require a little bit of tweaking depending on the server environment that you are on. What you can do is comment out a few rules at a time to determine which one is actually blocking the css, then continue to troubleshoot that particular rule.
Hi,
I’m using CI 2.0.2. Where the app folder lives outside the system folder.
On my hosting setup I have a subdomain.domain.com pointing to my root folder where the CI lives.
I would like to use the URL to match an application folder. So let me explain.
I have the following folder set up:
Application1
Application2
System
Index.php
.htaccess
I would like to use: subdomain.domain.com/application1/controller/method
And the .htaccess rules to rewrite it to:
Subdomain.domain.com/controller/method?app=application1
So then in the index.php I could get hold of the $_GET[‘app’] to match the application folder.
Could you help me with that rewriting rule?
Thank you
@Francisco, what I think you can do here is the following … I tried something similar a while back so i hope i am describing it well …
You should create a copy of your index.php (index2.php) … then in index2.php you can adjust your
$application_folder
var. For your rewrite rule you would have one pointing to index.php and another pointing to index2.php (but directory specific), something like:I am pretty sure this setup should work, I haven’t done it in a while. You might have to tweak it a bit to get it working just right.
I’ve set up your re-write but my url gets written with a question mark added in certain conditions.
If I go to:
http://domain.local/bla/bla
It gets re-written as
http://domain.local/?/bla/bla
I’m rubbish at reg expression and alike.
@Hank, check this post out. I’ve run into similar issues depending on the environment that I am running CI on.
Thanks for the reply.
I’ve settled with:
RewriteRule ^(welcome(/index)?|index(\.php))/$ / [L,R=301]
RewriteRule ^(.*)/index/?$ $1 [L,R=301]
The last ? has been removed from the first line.
This works for:
http://domain.local/controller/
But not:
http://domain.local/controller (note: the missing forward slash)
Thanks.
@Hank, keep the following in mind as you may have issues with POST data … CI tends to favor no-trailing slash.
My recommendation is to get it working without trailing slashes.
I’m using the re-write that removes trailing slashes also.
When I made reference to it working with:
1. http://domain.local/controller/
but not:
2. http://domain.local/controller
What I mean’t was, it successfully removes “controller/” leaving:
http://domain.local
Whereas 2. does not change.
What should be added to remove “controller”?
Thanks H
You will have a default controller set in CI, routes.php, by default this is the welcome controller, so in the rewrite rules if we detect welcome, we forward to / (root).
i follow this tutor, my default controller is ‘dashboard’, it works.people can check here http://jobcareer.polibatam.ac.id but when i tried do like http://jobcareer.polibatam.ac.id/login didn’t work.please help me..thx..
Your problem is a little strange as if you default controller is “dashboard” the following should return you to “/” … http://jobcareer.polibatam.ac.id/dashboard … you should confirm that you have codeigniter configured correctly and that your htaccess rewrites are actually working, per the tutorial above, see if some of the URLs are indeed being redirected.
thx dimas for reply, this my .htaccess file
config.php file
why still access index.php/dashboard/ ? not /dashboard/
Take a look at this, might solve your problem …
This is a great post. Thanks for taking care of all these details. These are often overlooked and can make a HUGE difference for SEO. I’ve seen sites of mine double their number of indexed pages, almost overnight, after making these improvements. It’s nice to have them done on my new project right from the start.
This only works if you have in your config.php file:
$config[‘uri_protocol’] = ‘AUTO’;
Which I hadn’t in first instance (QUERY_STRING).
Now it works fine.
All forms on my site now fail to post with the addition of the htaccess code. Could it be something to do with WAMPserver? I have followed the instructions exactly.
@Harry, if you have firebug, you will want to make sure that your forms POST/GET are not being redirected, else it may be loosing the data in between.
good art
@Johan van de Merwe +1
I had problems with my ajax get requests, had to change them to post and now works fine
You still have to do something in your controllers to prevent access to more than one URL for the same content. I tried using your rewrite_rules, while creating a simple blog controller
I can access the controllers comments-function through both http://www.fmground.dk/index.php/blog/comments and http://www.fmground.dk/blog/comments
which leaves an “open SEO wound” 🙂
help me pls..
i have virtual host like this :
domain => folder in server
hotels.visitbali.com => www/hotels
hotels.visitbali.com/kutahotel => www/kutahotel
if i access hotel.visitbali.com/kutahotel, there no problem.
but if i access hotel.visitbali.com/kutahotel/customer/booking, no page found.
customer is controller and booking is function
can someone help how about .htaccess ??
after pasting your .htaccess file, my default page goes to domain.ltd. even after i’ve deleted it already. how come?
@dude, browsers will sometime cache the request, so you might just need to restart your browser (chrome will do this sometimes)
So complete codeigniter htaccess tutorial, awesome…
Hi, Dimas. I’m a noob at this, and I crashed everything.
I pasted the file u posted into my htaccess file, and now, everytime I try to access my http://localhost/testweb, I get redirected into domain.tld. How can I fix it? Thank you
Did you copied and pasted without reading ?
it’s never a good idea.
to solve your problem, comment/remove the “enforce www” part and it should work better.
Plus search and replace the references to domain.tld with something approching your own project url
http://localhost/testweb
to avoid other bad behaviors, i would suggest you to look at using apache virtualhost as it is a good practise. search the web for “Apache Virtual Host”
I have read this. thanks for tut. i was searching for this . i have intranet with server name unicus-billion.And my CI path for my page is:
unicus-billion/resume/index.php/resumecontroller/load
alernatly i have used routes also
unicus-billion/resume/index.php/resumecontroller/load
same as
unicus-billion/resume/index.php/user.
after reading i have pasted & changed it. i got following error:-
———
Not Found
The requested URL /resume/resumecontroller/load was not found on this server.
Apache/2.2.6 (Win32) mod_ssl/2.2.6 OpenSSL/0.9.8g PHP/5.2.5 Server at unicus-billion Port 80
——–
will you please help me
to work my code simply without index.php in url.
thanks and regards
Sumit derbi
i got ‘404 Page Not Found’ error.plz help me .in .htaccess file .plz.
Thanks .
hi Dimas,
i follow your totorial,
i think i have same problem with @allis
i have virtual host like :
b3.menlh.go.id in directory : home/b3/www/MENLH
this website is like the parent portal cms base on joomla
then i want to put CI application on the same server ,
so CI application extracted on home/b3/www/MENLH/registrasi directory
here is my configuration :
$config[‘base_url’]= ‘http://b3.menlh.go.id/registrasi’;
$config[‘index_page’] = ”;
$config[‘uri_protocol’] =’AUTO’;
my default controller is “main”,
works fine when acces http://b3.menlh.go.id/registrasi
but i get error : “The requested URL /registrasi/main/login was not found on this server. ”
when acces http://b3.menlh.go.id/registrasi/main/login
plis help me dimas
thx so much 🙂
Good tutorial dude. Thanks
This was very helpful. Thanks for posting it.
hi.
I tried this but it keeps redirecting me to http://www.domain.tld/
any help
thanks
how to search index file function in route directory.
please solve the problem and get answer please quickly.
Your first “welcome” rule has a problem. It matches “welcomeindex” and “welcomeindex.php” (and not “welcome/index.php”
How to remove the controller name from the url
I have a HTML website with an issue:
Google Webmaster Tool shows duplicate pages:
http://www.domain.com/folder/
http://www.domain.com/folder/index.html
I want only http://www.domain.com/folder/index.html to be visible and accessible. How can this be done with .htaccess ?
REDIRECTING OLD DYNAMIC URLS :
Here’s a really usefull tip when you need to redirect old dynamic urls to new ones, specialy when there are GET vars in old urls (codeigniter refuse GET vars when using default config, and a simple Redirect 301 will fail)
Here’s the solution :
1. sample old url : page.php?id=1234&lang=en
2. sample new url : newpage/action/1234#contact
.htaccess :
RewriteCond %{REQUEST_URI} ^/page\.php$ [NC]
RewriteCond %{QUERY_STRING} id=([0-9]+)&lang=en$ [NC]
RewriteRule ^(.*)$ en/newpage/action/%1#contact? [NE,R=301,L]
Note that [NE] will allow to include an anchor in the destination url and the last caracter “?” will prevent query string to interfere with in the dest url.
Hope it’ll save someone’s time !
——————-
@SACHIN:
RewriteRule ^folder/?$ folder/index.html [R=301,L]
should do the trick
@sachin: you might replace [R=301,L] with [L]
I’ve got an improvement, reflecting current Apache rules —
change
# 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]
to read as
### Remove index.php from URL
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/+index\.php(/[^\s\?]+)? [NC]
RewriteRule ^ %1 [L,R=301]
# If your default controller is something other than
# “welcome” you should probably change this
RewriteRule ^(welcome(/index)?)/?$ / [L,R=301]
RewriteRule ^(.*)/index/?$ $1 [L,R=301]
This way, the index.php gets removed whenever it’s included in the URL, your current rules only remove it when it’s mentioned after /start/ which should produce a 404 error, and therefore defeating the purpose.
My method will remove it whenever it’s called after whatever RewriteBase is set to.
By reversing the following line :
RewriteRule ^(welcome(/index)?|index(\.php)?)/?$ / [L,R=301]
to something like :
RewriteRule ^/?$ /index.php [L,R=301]
Note: in “/index.php” you might remove the slash :unsure:
Hello,
Where should we put this .htaccess file(right next to index.php in the application folder ?)
Same question for those using codeigniter HMVC.
Thank you.