Nginx中配置thinkphp的URL重写

By | 2013年2月23日

前言

公司项目中使用了thinkphp框架,部署在apache中,很方便,可以参考thinkphp官网的doc:Apache URL重写

而在nginx下,网上没有很具体的文档,都是根据自己项目所配置,拿到别的项目中就行不通了,所以经过本人的研究,摸透了捕鱼方法!

既然使用了thinkphp,那就要对它的URL Mode有所了解。可以参考doc:URL 模式

准备工作

首先得做好一切准备了,比如nginx已经启动,项目已经部署完成,但是使用PATHINFO或者REWRITE链接访问页面出现404。

简单陈述下这里所用的项目(假设项目名为NicePrj)的结构:

  1. thinkphp框架
  2. 有多个project,统一放在application目录下
  3. URL MODE为REWRITE,即设置URL_MODEL 为2
  4. REWRITE链接类似如(用户登录页面):http://www…..com/appliction/prj3/user/login

目录结构也许是这样子的:

/var/www/html/niceprj/
	application/
		prj1/
		prj2/
		prj3/
		  Common/
		  Conf/
		  js/
		  Lang/
		  Lib/
		  Runtime/
		  Tpl/
		  index.php
	thinkphp/
	static/
	index.php

让我们先用兼容模式看看是否能正常访问,上面用户登录页面,使用兼容模式的链接看上去可以这么写:

http://www…..com/appliction/prj3/?m=user&a=login

或者加上index.php:

http://www…..com/appliction/prj3/index.php?m=user&a=login

在兼容模式下如果能访问页面,那么离成功不远了!

Nginx.conf配置

第一步配置

location / {
    root   /var/www/html/niceprj;
    index  index.php index.html index.htm;
    if (!-e $request_filename) {
		rewrite  ^/application/prj1/(.*)$  /application/prj1/index.php/$1  last;
		rewrite  ^/application/prj2/(.*)$  /application/prj2/index.php/$1  last;
                rewrite  ^/application/prj3/(.*)$  /application/prj3/index.php/$1  last;
              break;
	}	
}

if那一段是重点,我定义了三行rewrite, 我们需要理解的就是第二、第三个参数 。

第二个参数:对哪些地址进行rewrite,同时指定地址中哪部分内容作为URL参数传递。这里在/application/prj1/后面的内容将被认为是URL参数。

符合此定义的链接将被rewrite到第三个参数定义的规则中去。

第三个参数:处理第二个参数过来的URL参数。

比如访问用户登录页面:http://www…..com/appliction/prj3/user/login

user/login将作为URL参数传递到第三个参数,那么rewrite后的地址就是:http://www…..com/appliction/prj3/index.php/user/login

注意,第二个,三个参数可不能一样,如果你写成了:rewrite   ^/application/prj1/(.*)$   /application/prj1/$1  last;

那么页面将不停的刷新,刷新,刷新….死循环!此时第一件事就是,立马关掉窗口!

第二步配置

location ~ .+\.php($|/){
	set $script    $uri;
	set $path_info  "/";
	if ($uri ~ "^(.+\.php)(/.+)") {
		set $script     $1;
		set $path_info  $2;
	}
    root           /var/www/html/niceprj;
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  /var/www/html/niceprj$fastcgi_script_name;
    fastcgi_param  PATH_INFO $path_info;
    include        fastcgi_params;
}

通过上面的配置,fastcgi便支持PATHINFO模式的链接请求了,第一步配置中rewrite后的地址,将会拿到这里来处理,即交给php-cgi来处理。

这样一来就简单多了,您只需要修改网站目录路径了,将/var/www/html/niceprj改成自己的。其他一堆看上去像正则表达式的玩意儿就不用管它了(关于正则表达式,我是外行)

第三步配置

location ~ /\.ht {
    deny  all;
}

让nginx不要读取.htaccess文件!

总结

经过3步配置,已经完成了该配置的,总的配置看上去应该是这样的:

user  nobody;
worker_processes  5;
error_log  logs/error.log  info;
pid        logs/nginx.pid;
events {
    use epoll;
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile      on;
    tcp_nopush    on;
    tcp_nodelay   on;
    keepalive_timeout  10;
    gzip  on;
    server {
        listen       8080;
        server_name  localhost;
        charset utf-8;
        location / {
            root   /var/www/html/niceprj;
            index  index.php index.html index.htm;
            if (!-e $request_filename) {
			     rewrite  ^/application/prj1/(.*)$  /application/prj1/index.php/$1 last;
			     rewrite  ^/application/prj2/(.*)$  /application/prj2/index.php/$1 last;
                             rewrite  ^/application/prj3/(.*)$  /application/prj3/index.php/$1 last;
                             break;
        	}	
        }
        #location ~ \.php$ {
        location ~ .+\.php($|/){
        	set $script    $uri;
    		set $path_info  "/";
     		if ($uri ~ "^(.+\.php)(/.+)") {
        		set $script     $1;
        		set $path_info  $2;
     		}
            root           /var/www/html/niceprj;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  /var/www/html/niceprj$fastcgi_script_name;
            fastcgi_param  PATH_INFO $path_info;
            include        fastcgi_params;
        }
        location ~ /\.ht {
            deny  all;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

测试

打开浏览器测试下吧,如果有不对的地方(比如404,502,页面死循环样不停刷新(马上关掉页面!)),记得查看日志文件哦,默认为error_log文件。

在日志文件中可以看到,请求了哪个链接,转到了哪个链接。

通常出现问题的话,都是在第一步配置中的rewrite那一段,要根据自己项目的目录结构做调整。