当前位置: 首页 > 后端技术 > PHP

Nginx设置pathinfo函数来适配thinkphp5的路由模式

时间:2023-03-30 02:25:26 PHP

最近在把一个用thinkphp5写的项目部署到Centos7上,用的是nginx。部署后发现验证码出不来。分析了一波,发现是nginx无法解析thinkphp的路由规则,所以出现了404错误。网上的教程有的真的很好,有的真的是复制粘贴的。多么绕路啊。所以写下你的经历。我使用的是nginx1.14版本。在这个部署中,官网手册真的很重要。建议多看官网手册。这次我将解释两种写法。第一个位置/{root/usr/share/nginx/html;索引index.php;如果(!-e$request_filename){重写^/meeting/public/(.*)$/meeting/public/index.php?s=$1last;}}location~\.php{fastcgi_pass127.0.0.1:9000;fastcgi_indexindex.php;fastcgi_paramSCRIPT_FILENAME/usr/share/nginx/html$fastcgi_script_name;包括fastcgi_params;一个location的重写,官网是这样解释的:如果指定的正则表达式与请求URI匹配,则按照replacementstring中指定的方式更改URI。重写指令按照它们在配置文件中出现的顺序执行。简单的说就是url根据你的正则表达式进行转换。取上面第一个location块,假设url为/meeting/public/aaa/bbb/ccc,根据正则表达式.php?s=aaa/bbb/ccc,将其替换为/meeting/public/index,其中$1是通过(.*)$来匹配的,如果你有多个正则表达式,程序会把它赋值给$2,$3……,所以thinkphp是可以通过$_GET[的获取到的'].然后将请求转发到第二个location块,这样就可以访问了。但这也有缺点。如果我把?s=xxx写成?g=xxx会怎样?当然没用。我记得thinkphp用的是?s=xxx,或者我直接访问/meeting/public/index.php/aaa/bbb/ccc。根据上面的正则表达式,我们发现是行不通的。因为根本不访问第一个位置,而是直接访问第二个位置块,所以第二个位置不具备实现pathinfo的能力。所以访问失败。这里请注意,如果第二个位置是location~.php${,记得去掉$。第二种方法location/{root/usr/share/nginx/html;索引index.php;如果(!-e$request_filename){重写^/meeting/public/(.*)$/meeting/public/index.php/$1最后;}}location~\.php{fastcgi_pass127.0.0.1:9000;fastcgi_indexindex.php;fastcgi_split_path_info^(.+\.php)(.*)$;fastcgi_paramSCRIPT_FILENAME/usr/share/nginx/html$fastcgi_script_name;fastcgi_paramPATH_INFO$fastcgi_path_info;包括fastcgi_params;}第一个location的rewirite表达式其实和上一个差不多,假设url是/meeting/public/aaa/bbb/ccc,根据规律/index.php/会替换成/meeting/publicaaa/bbb/ccc,然后转发到第二个位置,第二个位置使用fastcgi_split_path_info。手册是这样解释的:定义一个捕获$fastcgi_path_info变量值的正则表达式。正则表达式应该有两个捕获:第一个捕获成为$fastcgi_script_name变量的值,第二个捕获成为$fastcgi_path_info变量的值。可以看看官网对两个变量的解释。这里,第二个位置通过fastcgi_split_path_info方法将/meeting/public/index.php/aaa/bbb/ccc按照正则划分为两个,一个是/meeting/public/index.php,赋值给$fastcgi_script_name,aaa/bbb/ccc被分配给$fastcgi_path_info。然后通过fastcgi_param将$fastcgi_script_name赋值给SCRIPT_FILENAME,再传给php服务器。$fastcgi_path_info也是如此。注意这里的SCRIPT_FILENAME和PATH_INFO是$_SERVER超级全局变量的键名,不能写错。通过这种方式,我们的第二个location块也具备了pathinfo的能力,克服了第一种方式的不足。