If you are a CodeIgniter enthusiast, you know that finding rewrite rules for Apache (htaccess file) is relatively easy, but doing the same for Nginx rewrite rules is not all that simple. Use these Nginx rewrite rules to get your next CodeIgniter project up and running.
So I had a little fun with Nginx this weekend, I setup a rackspace server, installed Nginx (with PHP and MySQL), and installed CodeIgniter.
If you are a CodeIgniter enthusiast, you know that finding rewrite rules for Apache (htaccess file) is relatively easy, but doing the same for Nginx rewrite rules is not all that simple. The rules that follow are from my original article: CodeIgniter htaccess (for Apache) and are an exact translation into Nginx rewrite rules.
CodeIgniter Nginx Config
Here is the entire config file that I use. 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).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
server { server_name .example.com; access_log /var/log/nginx/example .com.access.log; root /var/www/example .com /html ; index index.php index.html index.htm; # enforce www (exclude certain subdomains) # if ($host !~* ^(www|subdomain)) # { # rewrite ^/(.*)$ $scheme://www.$host/$1 permanent; # } # enforce NO www if ($host ~* ^www\.(.*)) { set $host_without_www $1; rewrite ^/(.*)$ $scheme: // $host_without_www/$1 permanent; } # canonicalize codeigniter url end points # if your default controller is something other than "welcome" you should change the following if ($request_uri ~* ^( /welcome ( /index )?| /index (.php)?)/?$) { rewrite ^(.*)$ / permanent; } # removes trailing "index" from all controllers if ($request_uri ~* index/?$) { rewrite ^/(.*) /index/ ?$ /$1 permanent; } # removes trailing slashes (prevents SEO duplicate content issues) if (!-d $request_filename) { rewrite ^/(.+)/$ /$1 permanent; } # removes access to "system" folder, also allows a "System.php" controller if ($request_uri ~* ^ /system ) { rewrite ^/(.*)$ /index .php?/$1 last; break ; } # unless the request is for a valid file (image, js, css, etc.), send to bootstrap if (!-e $request_filename) { rewrite ^/(.*)$ /index .php?/$1 last; break ; } # catch all error_page 404 /index .php; # use fastcgi for all php files location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /var/www/example .com /html $fastcgi_script_name; include fastcgi_params; } # deny access to apache .htaccess files location ~ /\.ht { deny all; } } |
Some Very Important Notes
I spent nearly half a day testing out these rules, so here are some important things I noticed:
- The PHP
DOCUMENT_ROOT
environment variable is derived from theroot
parameter and settingroot
on theserver
level vs within alocation
block is important. - Using the rewrite rules at the
server
level vs withinlocation
block is also key in their proper functionality, certain rules will not work properly otherwise.
Nginx Rewrite Rule Breakdown
The first 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.
11
12
13
14
15
16
17
18
19
20
21
22
|
# enforce www (exclude certain subdomains) #if ($host !~* ^(www|subdomain)) #{ # rewrite ^/(.*)$ $scheme://www.$host/$1 permanent; #} # enforce NO www if ($host ~* ^www\.(.*)) { set $host_without_www $1; rewrite ^/(.*)$ $scheme: // $host_without_www/$1 permanent; } |
I’ve also made some additions in an attempt to Canonicalize some of the CodeIgniter URL end points. The key benefit of a Canonicalized URL is that your search engine page ranking (page juice) is not spread across several pages, but instead, targeted to a single page.
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. These next set of rewrite rules prevent this:
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
# canonicalize codeigniter url end points # if your default controller is something other than "welcome" you should change the following if ($request_uri ~* ^( /welcome ( /index )?| /index (.php)?)/?$) { rewrite ^(.*)$ / permanent; } # removes trailing "index" from all controllers if ($request_uri ~* index/?$) { rewrite ^/(.*) /index/ ?$ /$1 permanent; } # removes trailing slashes (prevents SEO duplicate content issues) if (!-d $request_filename) { rewrite ^/(.+)/$ /$1 permanent; } |
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 rule prevents access to the system
directory and additionally allows you to have a System.php
controller file.
43
44
45
46
47
48
|
# removes access to "system" folder, also allows a "System.php" controller if ($request_uri ~* ^ /system ) { rewrite ^/(.*)$ /index .php?/$1 last; break ; } |
And the final rule is the catch all to route all requests to the bootstrap file.
50
51
52
53
54
55
|
# unless the request is for a valid file (image, js, css, etc.), send to bootstrap if (!-e $request_filename) { rewrite ^/(.*)$ /index .php?/$1 last; break ; } |
Apply These Final Touches to Clean Up the URL
Remember, once you have your CodeIgniter Nginx config 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 Nginx rewrites, the above will set your config file so that “index.php” will NOT show up as part of the URL as such:
instead your URLs will be cleaner:
If you have comments or improvement suggestions please let me know.