CodeIgniter在Nginx中的Rewrite Rules配置

JerryXia 发表于 , 阅读 (3,822)

为了学习CodeIgniter的使用,今天把www主机名下的一些页面改写了。可是由于在我本地测试是用的Apache Web服务器,正式发布用的是Nginx Web服务器,它是不支持Apache中的.htacess和pathInfo的,所以得重新作相关配置。

首先,推荐一个工具convert-apache-htaccess-to-nginx

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).

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 PHPDOCUMENT_ROOTenvironment variable is derived from therootparameter and settingrooton theserverlevel vs within alocationblock is important.
  • Using the rewrite rules at theserverlevel vs withinlocationblock 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.

# 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:

# 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 thesystemdirectory and additionally allows you to have aSystem.phpcontroller file.

# 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.

# 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:

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

instead your URLs will be cleaner:

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

添加新评论