Nginx下实现pathinfo及ThinkPHP的URL Rewrite模式支持(最新版)

1,打开Nginx的配置文件 /usr/local/nginx/conf/nginx.conf 一般是在这个路径,根据你的安装路径可能有所变化。如果你配置了vhost,而且只需要你这一个vhost支持pathinfo的话,可以直接打开你的 vhost的配置文件。找到类似如下代码(不同版本的nginx可能稍有不同,但是相差不会很远):

1
2
3
4
location ~ .*.(php|php5)?$
{
#原有代码
}

修改成以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#去掉$是为了不匹配行末,即可以匹配.php/,以实现pathinfo
#如果你不需要用到php5后缀,也可以将其去掉
location ~ .php
{
#原有代码

#定义变量 $path_info ,用于存放pathinfo信息
set $path_info "";
#定义变量 $real_script_name,用于存放真实地址
set $real_script_name $fastcgi_script_name;
#如果地址与引号内的正则表达式匹配
if ($fastcgi_script_name ~ "^(.+?\.php)(/.+)$") {
#将文件地址赋值给变量 $real_script_name
set $real_script_name $1;
#将文件地址后的参数赋值给变量 $path_info
set $path_info $2;
}
#配置fastcgi的一些参数
fastcgi_param SCRIPT_FILENAME $document_root$real_script_name;
fastcgi_param SCRIPT_NAME $real_script_name;
fastcgi_param PATH_INFO $path_info;
}

 

这样,nginx服务器就可以支持pathinfo了。

 

2,修改thinkphp让他可以在nginx上运行

修改nginx的rewrite

1
location / {  if (!-e $request_filename) {  rewrite ^(.*)$ /index.php?s=$1 last;  break;  }  }

然后项目配置下url模式改为2


1
'URL_MODEL'=>2,

如果是多个项目,布署项目时要把项目布署到目录里,如后台的项目放到Admin目录里,那么在nginx的rewrite里再写一条

1
location /admin/ {  if (!-e $request_filename) {  rewrite ^/admin/(.*)$ /admin/index.php?s=$1 last;  break;  }  }

 

最后也不要忘记把这个项目的url模式改为2。

 

什么是pathinfo以及thinkphp提供的url规则

1,tp提供的url规则

ThinkPHP框架基于M-V-C思想,模块化的设计并采用了单一入口模式(单一入口但并不是只能有一个入口),这样为nginx下的url重写免去了不少麻烦。

nginx下的基于ThinkPHP的应用的url重写,需了解ThinkPHP的各种url格式参数的处理逻辑以及nginx重写的原理。简单点说,无论哪种url格式,nginx都需要执行ThinkPHP下的应用单一入口文件,然后将各种url格式按照一定的格式规则进行进行参数化处理,最终执行指定模块与控制器;这个过程用户是看不到的,用户只能看到各种规则的url,这些url的规则如下:

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
#第一种 普通get多参数方式
http://blog.mallol.cn/index.php?m=Info&a=usrInfo

#第二种 pathinfo方式
http://blog.mallol.cn/index.php/Info/usrInfo
#带有get的其他变量
http://blog.mallol.cn/index.php/Info/usrInfo/Id/1

#第三种 普通get单参数方式 ThinkPHP中又称”兼容模式“
http://blog.mallol.cn/index.php?s=Info/usrInfo
#带有get的其他变量
http://blog.mallol.cn/index.php?s=Info/usrInfo/Id/1

/*
#当然这三种模式还可以附带文件后缀
#其实合并起来也就3种
#附带后缀只是上述三种规则的细微变化
#TinkPHP框架核心代码获取到以上三种模式的参数后
#会进行特定的处理 带不带后缀 带哪种后缀 均可配置
#也就是如下几种规则
*/

#第一种
http://blog.mallol.cn/index.php/Info/usrInfo.html
#第二种
http://blog.mallol.cn/index.php?s=Info/usrInfo.html

2,什么是pathinfo?pathinfo是php的功能,nginx并没有pathinfo功能,在php中书写如下代码:

1
2
3
4
5
<?php

print_r(pathinfo('http://blog.mallol.cn/test/index.txt'));

?>

结果:

1
2
3
4
5
6
7
Array
(
[dirname] => http://blog.mallol.cn/test
[basename] => index.txt
[extension] => txt
[filename] => index
)

通过以上运行结果,可以看到打印出来的数组key字段已经很明显的标示出其意义来了。

ThinkPHP就采用了这种思想,将单一入口的url传参格式化,典型的基于ThinKPHP的url示例如下:

1
http://blog.mallol.cn/index.php/Info/UsrInfo

简单点理解,上述格式化的url形式就是ThinkPHP需要支持的pathinfo路径模式。对这个种格式化的url进行稍微解释,访问这个么一个地址,对基于ThinkPHP框架的网站来说,实际需要执行的就是网站根目录下的index.php文件,而该url中后面的/Info/UsrInfo则被作为mvc思路中的功能模块参数与控制器参数,转换为普通get方式传参则上述url就要变为:

1
http://blog.mallol.cn/index.php?m=Info&a=UsrInfo

当然,get参数的变量该例子中一个是m一个是a,这个变量名在ThinkPHP中是可以改变的,这就需要依据具体的基于ThinkPHP的应用的模块规划与喜好了。

所以:

1
2
3
4
5
 if (!-e $request_filename) { 
rewrite ^(.*)$ /index.php?s=$1 last;
break;
}
它的目的是把http://blog.mallol.cn/info/usrInfo转换成http://blog.mallol.cn/index.php?s=info/usrInfo

后记:

前几天,我下了个ThinkCmf,按照上面的步骤配置了一遍,始终不行,只能首页打开,其他页面都是404 Not Found!.

我当时的服务器配置如下:

系统:ubuntu 14.04

nginx: 1.4.1

妈蛋,花了我差不多一天的时间,google baidu到天昏地暗,仍然404.真想扇Nginx几个耳刮子。最后我想升级下nginx版本试试。

所以:

1
2
ubuntu下:
sudo apt-get install nginx

升级后,nginx为1.8.0

此时当我再打开页面,奇迹发生了,一切正常。

.conf配置如下:

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
server {
listen 80;
server_name muscletech.mallol.cn www.muscletech.mallol.cn;
root /home/muscletech;
index index.html index.htm index.php default.html default.htm default.php;
error_log /home/logs/muscletech.log;
access_log /home/logs/muscletech.log;
#error_page 404 /404.html;

charset utf-8;

location / {
if (!-e $request_filename) {

rewrite ^(.*)$ /index.php?s=$1 last;

break;

}
}

location ~ \.php {
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;

}

location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 30d;
}
location ~ .*\.(js|css)?$
{
expires 1h;
}
#access_log /home/wwwroot/wwwlogs/phpmyadmin.log main;
}

谨记:以后如果超过1个小时解决不了的话,建议先升级一下nginx看看。

 

坚持原创技术分享,您的支持将鼓励我继续创作!