Nginx如何实现pathinfo模式的方法详解
什么是pathinfo模式呢?
pathinfo是伪静态的一种,我们先解释一下伪静态的概念,伪静态页面是静态URL与动态URL互通的一个桥梁,它是指动态网址通过URL重写的手段去掉其动态参数,使URL静态化,但在实际的网页目录中并没有重写URL。简单来说,伪静态URL就是通过服务器转换伪装文件名或地址,使该页面类似于静态页面,但服务器上没有独立存在的文件,其本质还是动态页面。
使用过ThinkPHP框架开发应用的同学应该都会知道,它有一种URL模式就是pathinfo,看起来类似下面的URL:
http://example.com/module/controller/action/key1/value1/key2/value2.html
其实上面的URL的原型是下面的样子:
//这个才是正宗的URL,上面那个是冒牌的 http://example.com/index.php?m=module&c=controller&a=action&key1=value1&key2=value2
既然pathinfo模式的URL不是正宗的,那为什么不用正宗的呢,用正宗的不好吗?相对于正宗的URL,pathinfo模式的确实是有优势的,以下简单列举几项它的好处。
- 它提供了最好的SEO支持
- 可以实现URL的伪静态
- 它看起来更简洁、更好看
pathinfo模式的URL有这么多优点,那我们肯定要支持了。ThinkPHP更多的URL模式配置及实现,可以参考这篇文档。
本文主要讨论的是pathinfo模式的URL在Nginx中的实现,ThinkPHP官方文档中没有介绍,但是它实现起来也挺简单的。以下是实现过程的一些思考。
一个标准的通用的URL格式是类似下面那样子的:
:// : @ : / ; ? #
参照通用的URL格式,对比可以发现,pathinfo模式的相对于标准模式的URL,有两个地方的区别比较大,一个是没有了index.php文件,另一个是查询参数并没有使用符号“?”隔开。
现在要做的就是在Nginx接收的pathinfo模式的URL请求时,将它还原成标准的URL模式,这样服务器就能正常处理了。
把缺失的index.php文件补上
这个需要用到Nginx的rewrite指令,它的作用是将请求的URI替换成目标URL。在这里需要达到的效果是,将
http://example.com/module/controller/action/key1/value1/key2/value2.html
替换成
http://example.com/index.php/module/controller/action/key1/value1/key2/value2.html
当然,并不是所有的URI都会进行此规则的重写,只有那些不是文件的URI才进行重写。所以,关于重写的指令将会类似下面的:
#如果请求的文件不存在,则进行URI重写 #在原有的基础上添加入口文件index.php if(!-e$request_filename){ rewrite^/(.*)$/index.php/$1last; }
通过以上配置就能达到补全index.php入口文件的效果了。
区分符号?前后的内容
在通用的URL中,符号“?”是具有特殊作用的,它是用来将查询字符串和前面的文件隔开。在pathinfo模式的URL中,符号“?”没有了,也就是说,服务器无法区分URI中哪些是文件,哪些是查询字符串了。所以,我们的目的是将pathinfo模式中本来应该由符号“?”区分的内容给手动区分开来。
还好,Nginx中有个指令可以实现我们的目的,fastcgi_split_path_info。它可以将正则表达式定义的两个串分别赋值给变量$fastcgi_script_name和变量$fastcgi_path_info,以供后文使用。更多关于fastcgi_split_path_info的信息,请查阅这里
相关配置类似下面的代码:
location~^(.+\.php)(.*)${ root/var/www/html/$vhost_path; fastcgi_passphpfpm:9000; fastcgi_split_path_info^(.+\.php)(.*)$; fastcgi_paramSCRIPT_FILENAME$document_root$fastcgi_script_name; fastcgi_paramPATH_INFO$fastcgi_path_info; includefastcgi_params; }
一个简单的例子
通过上面两部份的配置,现在的Nginx服务器已经支持pathinfo模式的URL了,以下是一个简单的server配置,仅供参考:
server{ listen80; server_nametp5.loc; set$vhost_pathtp5/public; location/{ root/usr/share/nginx/html/$vhost_path; indexindex.phpindex.htmlindex.htm; if(!-e$request_filename){ rewrite^/(.*)$/index.php/$1last; } } location~^(.+\.php)(.*)${ root/var/www/html/$vhost_path; fastcgi_passphpfpm:9000; fastcgi_split_path_info^(.+\.php)(.*)$; fastcgi_paramSCRIPT_FILENAME$document_root$fastcgi_script_name; fastcgi_paramPATH_INFO$fastcgi_path_info; includefastcgi_params; } }
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。