友声网

 找回密码
 立即注册
搜索
开启左侧

[Nginx] Nginx下PHP支持path_info的方法(PHP/fastcgi)

[复制链接]
卡卡北 发表于 2018-12-27 21:05 | 显示全部楼层 |阅读模式
Nginx(PHP/fastcgi)的PATHINFO配置

PATHINFO是一个CGI 1.1的标准,经常用来做为传参载体,在Apache中, 当不加配置的时候, 对于PHP脚本, AcceptPathInfo是默认接受的,而对于Nginx下, 是不支持PATHINFO 的, 也就是需要设置才能使用PATHINFO模式.

我们可以使用PATH_INFO来代替Rewrite来实现伪静态页面, 很多PHP框架也使用PATHINFO模式来作为路由载体

Apache 默认设置PATHINFO原理分析
  1. #对于请求https://www.ys166.com/index.php/login/index

  2. #Apache都接受, 都会认为是对index.php的访问, 并会设置PATH_INFO为'/login/index'
复制代码


print_r($_SERVER["PATH_INFO"]);//login/index

nginx 模拟PATH_INFO

Nginx是通过对文件名的扩展名匹配,来决定是否要交给php cgi服务器去解释的.在nginx.conf中一般都有如下的默认配置段:
  1. location ~ .php$ {
  2. fastcgi_index index.php;
  3. fastcgi_pass 127.0.0.1:9000;
  4. include fastcgi_params;
  5. }
复制代码

对于形如tools/index.php/login/index这样的文件路径, Nginx正则匹配为路径而不是php文件. 所以我们需要去掉($)改写这段配置匹配扩展名:
  1. location ~ .php {
  2. fastcgi_index index.php;
  3. fastcgi_pass 127.0.0.1:9000;
  4. include fastcgi_params;
  5. }
复制代码

现在, 脚本路径已经交由PHP自己处理了. 那怎么增加PATH_INFO呢?

方案一:php内置解析

我们需要打开PHP中cgi.fix_pathinfo配置项, 打开这个配置项以后, PHP会去根据CGI规范来检查SCRIPT_FILENAME中那部分是访问脚本和PATH_INFO(ini配置解释), 并根据SCRIPT_NAME来修改PATH_INFO(和PATH_TRANSLATED)为正确的值然后, 就只要添加一个FASTCGI_PARAM项就好了:
  1. location ~ .php {
  2. fastcgi_index index.php;
  3. fastcgi_pass 127.0.0.1:9000;
  4. include fastcgi_params;
  5. fastcgi_param PATH_INFO $fastcgi_script_name;
  6. }
复制代码


方案二:nginx正则解析

上面的解决方法, 把对路径的分析交给了PHP去处理,下面是由Nginx来分析路径(也就不需要fix_pathinfo),两种配置方案
  1. #配置方案 使用nginx模块fastcgi_split_path_info(nginx版本>0.7.31)
  2. location ~ \.php {
  3. fastcgi_pass   127.0.0.1:9000;
  4. fastcgi_index  index.php;
  5. #先加载默认后解析赋值
  6. include        fastcgi_params;
  7. #正则解析路径
  8. fastcgi_split_path_info ^((?U).+\.php)(/?.+)$;
  9. fastcgi_param  PATH_INFO        $fastcgi_path_info;
  10. fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
  11. }
复制代码

  1. /*
  2. fastcgi_split_path_info
  3. 语法:fastcgi_split_path_info regex
  4. 使用字段:location
  5. 可用版本:0.7.31以上
  6. 这个指令允许为CGI specification设置SCRIPT_FILENAME、SCRIPT_NAME、PATH_INFO变量。正则包含两个组:
  7. 处理请求的脚本路径–>对应$fastcgi_script_name
  8. 脚本参数的值–>      对应$fastcgi_path_info
  9. */
  10. location ~ ^.+\.php {
  11. (...)
  12. fastcgi_split_path_info ^(.+\.php)(.*)$;
  13. fastcgi_param PATH_INFO       $fastcgi_path_info;
  14. fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
  15. fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
  16. (...)
  17. }
  18. /*
  19. 示例请求”/show.php/article/0001”的参数SCRIPT_FILENAME将设置为”/path/to/php/show.php”,参数PATH_INFO为”/article/0001”*/
复制代码
  1. #配置方案2
  2. #由于nginx内建只读变量$fastcgi_script_name无法赋值,所有通过设置$real_script_name变量来做中间值
  3. location ~ \.php {
  4. fastcgi_pass   127.0.0.1:9000;
  5. fastcgi_index  index.php;
  6. #先加载默认后解析赋值
  7. include        fastcgi_params;
  8. #正则解析路径
  9. set $path_info "";
  10. set $real_script_name $fastcgi_script_name;
  11. if ($fastcgi_script_name ~ "^(.+?\.php)(/.+)$") {
  12. set $real_script_name $1;
  13. set $path_info $2;
  14. }
  15. fastcgi_param PATH_INFO       $path_info;
  16. fastcgi_param SCRIPT_FILENAME $document_root$real_script_name;
  17. fastcgi_param SCRIPT_NAME     $real_script_name;
  18. }
复制代码
  1. /*nginx 把nginx解析url变量赋值给fastcgi_param,php通过$_SERVER获取fastcgi_param中的所有变量值 */
  2. Array
  3. (
  4. [USER] => www
  5. [HOME] => /home/www
  6. [FCGI_ROLE] => RESPONDER
  7. [QUERY_STRING] =>
  8. [REQUEST_METHOD] => GET
  9. [CONTENT_TYPE] =>
  10. [CONTENT_LENGTH] =>
  11. [SCRIPT_NAME] => /demos/doitnote/index.php  //重点关注
  12. [REQUEST_URI] => /demos/doitnote/index.php/login/index
  13. [DOCUMENT_URI] => /demos/doitnote/index.php/login/index
  14. [DOCUMENT_ROOT] => /mnt/hgfs/vmhtml/doitphp
  15. [SERVER_PROTOCOL] => HTTP/1.1
  16. [GATEWAY_INTERFACE] => CGI/1.1
  17. [SERVER_SOFTWARE] => nginx/1.1.19
  18. [REMOTE_ADDR] => 192.168.127.1
  19. [REMOTE_PORT] => 60422
  20. [SERVER_ADDR] => 192.168.127.10
  21. [SERVER_PORT] => 80
  22. [SERVER_NAME] => [url]www.doitphp.loc[/url]
  23. [REDIRECT_STATUS] => 200
  24. [PATH_INFO] => /login/index  //重点关注
  25. [SCRIPT_FILENAME] => /mnt/hgfs/vmhtml/doitphp/demos/doitnote/index.php  //重点关注
  26. [HTTP_HOST] => [url]www.doitphp.loc[/url]
  27. [HTTP_USER_AGENT] => Mozilla/5.0 (Windows NT 6.1; rv:16.0) Gecko/20100101 Firefox/16.0
  28. [HTTP_ACCEPT] => text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  29. [HTTP_ACCEPT_LANGUAGE] => zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
  30. [HTTP_ACCEPT_ENCODING] => gzip, deflate
  31. [HTTP_CONNECTION] => keep-alive
  32. [HTTP_REFERER] => [url]http://www.doitphp.loc/demos/doitnote/[/url]
  33. [HTTP_CACHE_CONTROL] => max-age=0
  34. [PHP_SELF] => /demos/doitnote/index.php/login/index
  35. [REQUEST_TIME] => 1354246274
  36. )
复制代码
 楼主| 卡卡北 发表于 2018-12-27 21:06 | 显示全部楼层
其他方法:
nginx服务器开启phpinfo模式:
location ~ [^/]\.php(/|$)
  1. {
  2.   # comment try_files $uri =404; to enable pathinfo
  3.   #try_files $uri =404; #把这行代码注释,让服务器不尝试去加载路径文件
  4.   fastcgi_pass unix:/tmp/php-cgi.sock;
  5.   fastcgi_index index.php;
  6.   include fastcgi.conf;
  7.   include pathinfo.conf; #加载phpinfo.conf配置
  8. }
复制代码
 楼主| 卡卡北 发表于 2018-12-27 21:27 | 显示全部楼层
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|RSS|联系|友声网 ( 鲁ICP备15020090号 ) 知道创宇云安全

GMT+8, 2019-2-23 00:21 , Processed in 0.083988 second(s), 17 queries , MemCache On.

Powered by Discuz! X

©2019 Comsenz Inc.

快速回复 返回顶部 返回列表