配置Nginx+PHP的正确思路与过程


Posted in PHP onMay 10, 2016

对很多人而言,配置Nginx+PHP无外乎就是搜索一篇教程,然后拷贝粘贴。听上去似乎也没什么问题,可惜实际上网络上很多资料本身年久失修,漏洞百出,如果大家不求甚解,一味的拷贝粘贴,早晚有一天会为此付出代价。

如何正确配置 Nginx+PHP

假设我们用PHP实现了一个前端控制器,或者直白点说就是统一入口:把PHP请求都发送到同一个文件上,然后在此文件里通过解析「REQUEST_URI」实现路由。

一般这样配置

此时很多教程会教大家这样配置Nginx+PHP:

server {
  listen 80;
  server_name foo.com;

  root /path;

  location / {
    index index.html index.htm index.php;

    if (!-e $request_filename) {
      rewrite . /index.php last;
    }
  }

  location ~ /.php$ {
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME /path$fastcgi_script_name;
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index index.php;
  }
}

这里面有很多错误,或者说至少是坏味道的地方,大家看看能发现几个。

我们有必要先了解一下Nginx配置文件里指令的继承关系:

Nginx配置文件分为好多块,常见的从外到内依次是「http」、「server」、「location」等等,缺省的继承关系是从外到内,也就是说内层块会自动获取外层块的值作为缺省值。

让我们先从「index」指令入手吧

在问题配置中它是在「location」中定义的:

location / {
  index index.html index.htm index.php;
}

一旦未来需要加入新的「location」,必然会出现重复定义的「index」指令,这是因为多个「location」是平级的关系,不存在继承,此时应该在「server」里定义「index」,借助继承关系,「index」指令在所有的「location」中都能生效。

接下来看看「if」指令

说它是大家误解最深的Nginx指令毫不为过:

if (!-e $request_filename) {
  rewrite . /index.php last;
}

很多人喜欢用「if」指令做一系列的检查,不过这实际上是「try_files」指令的职责:

try_files $uri $uri/ /index.php;
除此以外,初学者往往会认为「if」指令是内核级的指令,但是实际上它是rewrite模块的一部分,加上Nginx配置实际上是声明式的,而非过程式的,所以当其和非rewrite模块的指令混用时,结果可能会非你所愿。

下面看看「fastcgi_params」配置文件

include fastcgi_params;
Nginx有两份fastcgi配置文件,分别是「fastcgi_params」和「fastcgi.conf」,它们没有太大的差异,唯一的区别是后者比前者多了一行「SCRIPT_FILENAME」的定义:

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
注意:$document_root 和 $fastcgi_script_name 之间没有 /。

原本Nginx只有「fastcgi_params」,后来发现很多人在定义「SCRIPT_FILENAME」时使用了硬编码的方式,于是为了规范用法便引入了「fastcgi.conf」。

不过这样的话就产生一个疑问:为什么一定要引入一个新的配置文件,而不是修改旧的配置文件?这是因为「fastcgi_param」指令是数组型的,和普通指令相同的是:内层替换外层;和普通指令不同的是:当在同级多次使用的时候,是新增而不是替换。换句话说,如果在同级定义两次「SCRIPT_FILENAME」,那么它们都会被发送到后端,这可能会导致一些潜在的问题,为了避免此类情况,便引入了一个新的配置文件。

此外,我们还需要考虑一个安全问题:在PHP开启「cgi.fix_pathinfo」的情况下,PHP可能会把错误的文件类型当作PHP文件来解析。如果Nginx和PHP安装在同一台服务器上的话,那么最简单的解决方法是用「try_files」指令做一次过滤:

try_files $uri =404;

改良后的版本

依照前面的分析,给出一份改良后的版本,是不是比开始的版本清爽了很多:

server {
  listen 80;
  server_name foo.com;

  root /path;
  index index.html index.htm index.php;

  location / {
    try_files $uri $uri/ /index.php$is_args$args;
  }

  location ~ /.php$ {
    try_files $uri =404;

    include fastcgi.conf;
    fastcgi_pass 127.0.0.1:9000;
  }
}

如何正确配置 Nginx + PHP,相信大家应该有了自己的认识了吧!

PHP 相关文章推荐
ezSQL PHP数据库操作类库
May 16 PHP
PHP语言中global和$GLOBALS[]的分析 之二
Feb 02 PHP
php中使用接口实现工厂设计模式的代码
Jun 17 PHP
利用php实现禁用IE和火狐的缓存问题
Dec 03 PHP
PHP数组传递是值传递而非引用传递概念纠正
Jan 31 PHP
比较简单的百度网盘文件直链PHP代码
Mar 24 PHP
Codeigniter操作数据库表的优化写法总结
Jun 12 PHP
PHP实现AES256加密算法实例
Sep 22 PHP
codeigniter中实现一次性加载多个view的方法
Mar 20 PHP
Yii使用Captcha验证码的方法
Dec 28 PHP
PHP大文件切割上传并带进度条功能示例
Jul 01 PHP
php多进程中的阻塞与非阻塞操作实例分析
Mar 04 PHP
WordPress中设置Post Type自定义文章类型的实例教程
May 10 #PHP
php+MySQL实现登录时验证登录名和密码是否正确
May 10 #PHP
PHP7+Nginx的配置与安装教程详解
May 10 #PHP
php+mysql实现的二级联动菜单效果详解
May 10 #PHP
浅析Yii2缓存的使用
May 10 #PHP
php简单统计在线人数的方法
May 10 #PHP
使用php实现从身份证中提取生日
May 09 #PHP
You might like
php批量上传的实现代码
2013/06/09 PHP
php中static和const关键字用法分析
2016/12/07 PHP
简单解决微信文章图片防盗链问题
2016/12/17 PHP
自制PHP框架之路由与控制器
2017/05/07 PHP
PHP面向对象程序设计之对象的遍历操作示例
2019/06/12 PHP
asp.net HttpHandler实现图片防盗链
2009/11/09 Javascript
js 页面刷新location.reload和location.replace的区别小结
2009/12/24 Javascript
Web开发者必备的12款超赞jQuery插件
2010/12/03 Javascript
animate动画示例(泪奔的小孩)及stop和delay的使用
2013/05/06 Javascript
js操作table示例(个人心得)
2013/11/29 Javascript
js点击button按钮跳转到另一个新页面
2014/10/10 Javascript
jQuery简单实现彩色云标签效果示例
2016/08/01 Javascript
利用Javascript仿Excel的数据透视分析功能
2016/09/07 Javascript
深入理解Angularjs向指令传递数据双向绑定机制
2016/12/31 Javascript
jQuery模拟下拉框选择对应菜单的内容
2017/03/07 Javascript
vue2 自定义动态组件所遇到的问题
2017/06/08 Javascript
vue父组件中获取子组件中的数据(实例讲解)
2017/09/27 Javascript
Angular 4.x+Ionic3踩坑之Ionic3.x pop反向传值详解
2018/03/13 Javascript
node.js学习笔记之koa框架和简单爬虫练习
2018/12/13 Javascript
Typescript的三种运行方式(小结)
2019/09/18 Javascript
解决微信授权成功后点击按返回键出现空白页和报错的问题
2020/06/08 Javascript
解决vue中el-tab-pane切换的问题
2020/07/19 Javascript
axios封装与传参示例详解
2020/10/18 Javascript
Python数据结构之翻转链表
2017/02/25 Python
用Python编写一个高效的端口扫描器的方法
2018/12/20 Python
详解用pyecharts Geo实现动态数据热力图城市找不到问题解决
2019/06/26 Python
python正则表达式匹配不包含某几个字符的字符串方法
2019/07/23 Python
Python 通过微信控制实现app定位发送到个人服务器再转发微信服务器接收位置信息
2019/08/05 Python
css3实现二维码扫描特效的示例
2020/10/29 HTML / CSS
护士实习鉴定范文
2013/12/22 职场文书
教职工代表大会主持词
2014/04/01 职场文书
艺术设计专业毕业生推荐信
2014/07/08 职场文书
房屋买卖授权委托书
2014/09/27 职场文书
事业单位考察材料范文
2014/12/25 职场文书
总结一下关于在Java8中使用stream流踩过的一些坑
2021/06/24 Java/Android
Java 垃圾回收超详细讲解记忆集和卡表
2022/04/08 Java/Android