rewrite/try_files命令rewrite/try_files都是处理$uri(不包括$query_string),但是rewrite会保留原来的请求$query_string,try_files会被丢弃,这就是为什么$query_string通常在重写try_files时添加。location/{if(!-e$request_filename){#rewritedealswith$uri,$1matchedby^(.*)$实际上是$urirewrite^(.*)$/index.php$1last;最后重写^(.*)$/index.php$uri;#这样写break没有区别;}#非pathinfo改写#适用于使用$_SERVER['request_uri']中路径进行路由分析的框架laravel/yii2#所以重写不传$uri也无所谓#但必须加上$is_args$query_string,否则$_GET为空try_files$uri$uri//index.php$is_args$query_string;_SERVER['path_info']Thinkphp,一个路由分析框架#$is_args$query_string可以省略#因为标准pathinfo要求参数在$uri中进行路径#没有$_GET参数try_files$uri$uri//index.php$uri$is_args$query_string;}$document_root很简单,网站的根目录,没什么服务器{root/home/wwwroot/site/public;}$request_uri请求资源定位器。即你在浏览器中输入的原始url(去掉host),$request_uri在整个请求会话中是固定不变的($uri可能会因为重写规则被nginx重新定义,但$request_uri不会改变)。注意:请求资源定位符是用queryString修改的。/index.php/news/index?p=1&ps=10/news/index?p=1&ps=10$uri请求的资源名称和资源定位符$request_uri的区别在于资源定位符只是一个符号,其中可能是通过映射改写的,$uri是nginx解析$request_uri后得到的资源名。$uri最初是没有$query_string的$request_uri,但是nginx可能会重写你的请求。改写后,最终的$uri可能与$request_uri不同,所以$uri没有改写,即$request_uri去掉了可能携带的$query_string。如果发生重写,则取决于重写后的最终资源名称。#重写规则location/{try_files$uri$uri//index.php$uri;}location~[^/]\.php(/|$){....}#不重写直接命中location/index.php/news/index?p=1&ps=10$request_uri=/index.php/news/index?p=1&ps=10$uri=/index.php/news/index#hit/triggeredintry_files重写/news/index?p=1&ps=101,$request_uri=$uri=/news/index?p=1&ps=102,hitlocation/{try_files$uri$uri//index.php$uri;}3、重写解析4、$request_uri=/news/index?p=1&ps=105,$uri=/index.php/news/index$query_string/$args&$is_argsurl的queryString参数,$query_string和$args正好同样,$is_args是友好的表示queryString是否带,带'?',不带''。/news/list?p=1&ps=10$query_string=$args=p=1&ps=10$is_args=?#改写的时候,用$is_args追加$query_string,这样比较规范location/{try_files$uri$uri//指数。php$is_args$query_string;}$request_filename计算表达式:$request_filename=$document_root$uri请求的资源文件路径,这个变量在你的$request_uri被解析处理后与$document_root结合得到最终的$uri生成。服务器{root/home/wwwroot/site/public/index.php/news/list;}/index.php/new/list?p=1&ps=10$request_uri=/index.php/news/list?p=1&ps=10$uri=/index.php/new/list$request_filename=$document_root$uri=/home/wwwroot/site/public/index.php/news/listfastcgi_script_name/fastcgi_path_info这两个变量放在一起比较好,default一般情况下$fastcgi_script_name=$uri,但是我们大部分的url为了美观使用pathinfo样式。所以,如果你将/index.php/news/index直接传递给php,那么$_SERVER['SCRIPT_NAME']='/index.php/news/index'。而pathinfo处理后:#fastcgi_split_path_info命令会做如下处理#将$1赋值给$fastcgi_script_name#赋值$2给$fastcgi_path_info#这样我们就可以得到实际可以执行的php脚本名,脚本文件名和路径由脚本fastcgi_split_path_info^(.+?\.php)(/.+)$;fastcgi_paramSCRIPT_NAME$fastcgi_script_name;fastcgi_paramSCRIPT_FILENAME$document_root$fastcgi_script_name;fastcgi_paramPATH_INFO$fastcgi_path_info;fastcgi_paramPATH_TRANSLATED$document_root_1$=fastcgi,request1&ps=10$request_uri=/news/index?p=1&ps=10$uri=/news/index?p=1&ps=102.重写:/index.php/news/index?p=1&ps=10$uri=/index.php/news/index$request_filename=/home/wwwroot/site/public/index.php/news/index$fastcgi_script_name=$uri3.pahtinfoparsefastcgi_split_path_info^(.+?\.php)(/.+)$;$fastcgi_script_name=/index.php$fastcgi_path_info=/news/index#用fastcgi_paramSCRIPT_NAME填充php的一些$_SERVER变量$fastcgi_script_name;fastcgi_paramSCRIPT_FILENAME$document_root$fastcgi_script_name;fastcgi_paramPATH_INFO$fastcgi_path_info;fastcgi_paramPATH_TRANSLATED$document_root$fastcgi_path_info;我们可以使用$_SERVER['PATH_INFO']进行路由和参数处理。现在很多开发者可能直接使用框架上手,框架在给效率的同时,也可能导致开发者忽略很多底层细节。比如单入口文件类型的框架,所有请求的资源文件其实只是index.php,框架负责解析你输入的“资源路径”。路由,处理。常规的url/index.php?ctrl=news&action=index&p=1&ps=10框架实际理解处理的url如上,框架最终会将你的url解析映射到对应的controller&action。nginx的$uri是/index.php。资源url/index.php/news/index?p=1&ps=10/news/index?p=1&ps=10框架:yii2/laravel。请求资源的路径变了,查询参数还是正常的方式。对于seo的爬虫,服务上有一个资源:/news/index,nginx的$uri是/index.php/news/index或者/news/index,比常规的url更加友好。基于Pathinfo的url/news/index/p/1/ps/10框架:thinkphp。查询参数也是面向路径的。对于SEO爬虫,服务上有一个资源:/news/index/p/1/ps/10,nginx的$uri是/news/index/p/1/ps/10。thinkphp完全支持各种框架的url方式和pathinfo的url方式,传入和生成的url无需特殊处理。yii2/laravel的路由声明并不是100%支持的,没有办法自动将queryString添加到pathinfo中。对于yii2/laravel来说,queryString参数也是基于pathinfo的,但是路由语句在某些场景下会显得多余(参数少且固定还好,多了又不固定就尴尬了)。ThinkphpTP具有pathinfo风格的url,可以解析处理面向pathinfo的queryString,使用框架的urlhelper方法生成pathinfo风格的链接。为什么说TP非常尊重pathinfo呢?官方的url重写规则是不带queryString的try_files重写。因此,TP告诉您queryString参数也应该是$uri的路径信息。#Pathinfo方式的重写规则location/{#try_files本质上不是重写,你传什么它都会请求,这里只传$uri,不传$query_string#请求重入时,$query_string为空try_files$uri$uri//index.php$uri;#兼容老版本的nginxif(!-e$request_filename){#两者选其一没有区别#rewriteonlyprocesses$uri(no$query_string)#^(.+)$常规的也是$uri,所以$1中没有$query_string#但是rewrite会隐式的保留请求上下文中的$query_string即使rewrite没有通过#重写后的请求中仍然有$query_stringrewrite^(.+)$/index.php$1最后;休息;最后重写$uri/index.php$uri;休息;}}url辅助函数生成的链接样式/?s=/news/index&p=1&ps=10//普通模式/news/index/p/1/ps/10//pathinfo模式Yii2Yii2的prettyUrl不是完整的pathinfomode,它只是路径化请求的“资源文件”,资源文件的描述参数queryString仍然使用普通模式。prettyUrl方式的重写规则location/{#try_files必须加$query_string,不加get参数会丢失try_files$uri$uri//index.php$is_args$query_string;#兼容老版本的nginx#rewrite加不加$query_string是一样的context会保留if(!-e$request_filename){rewrite^(.+)$/index.phplast;休息;最后重写$uri/index.php;休息;}}注意到yii2不是必须携带$uri转发了吗?下面的laravel也是如此。因为yii2/laravel的路由解析$request_uri,重写的url只是用来传递queryString给框架,框架会使用nginx::$request_uri=>php::$_SERVER['REQUEST_URI'中的路径信息]执行路由分析。/news/index?p=1&ps=10nginx::$request_uri=/news/index?p=1&ps=10php::$_SERVER['REQUEST_URI']=/news/index?p=1&ps=10$routePath='/news/index'$routeCtrl='news'$routeAction='index'$requestQueryString=$_GET'urlManager'=>['enablePrettyUrl'=>true,'showScriptName'=>false,//帮助手生成链接时隐藏/index.php'enableStrictParsing'=>true,'rules'=>[['class'=>'yii\rest\UrlRule','controller'=>['v1/news'],'pluralize'=>false,//自动复制数],'GET/
