通过一下午对 NGINX 的官方文档的研究和不断的尝试,对之前的 nginx.conf 做了蛮大的修改(请参见之前的文章《PHP 全局变量 PATH_INFO 与 NGINX 的配置》《让 symfony 运行在 NGINX 上的完美配置》不靠谱的百度空间已经把我之前的文章完全删除了,不过也无所谓,有了这篇文章后,之前写的也没太多价值了),下面将对优化后的版本进行详细的解释。
2016-1-10 更新:请跳转至此参考更“现代”的配置方式
因为 symfony 框架的 webserver 配置要求算是目前比较典型的 PHP 配置要求,所以还以它举例子:
server {
set $project_root /path/to/project;
server_name test.localhost;
root $project_root/web; # www 根目录
index index.php;
# ^~ 是往前普通匹配,这里表示 /sf/ 开头的 uri
# 在 prod 环境下其实这个可以不用配置
location ^~ /sf/ {
# alias 用来替换原本的 root 路径
alias $project_root/lib/vendor/symfony/data/web/sf/;
# 由于 /sf/ 下都是静态文件所以设置为最大过期时间
expires max;
}
# ~ 是正则匹配,这里匹配php文件
location ~ ^/(index|frontend_dev)\.php($|\/) { # 只有在这里列出来的 PHP 脚本才能执行,防止 nginx 的上传文件漏洞
# 交给 php-cgi 处理
fastcgi_pass 127.0.0.1:9000;
# 此文件里面还需另外设置,后面单独说明
include fastcgi_params;
}
# 这里正则匹配所有有扩展名的文件
# 如果规定只静态文件有扩展名,那么等于匹配静态文件
location ~ \.\w+ {
# 做运维的会发现常有人恶意企图抓取
# .db,.mdb,.sql,.xml 等数据文件
# 导致大量404访问
# php 大部分大型框架在一个请求过来以后
# 都会做若干初始化工作
# 所以如果不做特殊处理,php 会消耗大量资源去处理
# 这种本来 nginx 直接给 404 就可以处理的事情
expires max;
# 但这里也有一个缺点
# 必须规定好所有的动态页面的 uri 必须没有扩展名
# 也就是说使用此配置
# 将不能做类似伪静态的事情了
# (比如动态生成.html结尾的页面)
}
# 上面规则都无法匹配的uri,都会执行此规则
location / {
# 直接 rewrite 到根目录下 index.php
# 因为不是 30X 跳转,所以 path_info 变量并不会改变
rewrite .* /index.php last;
}
}
另外 fastcgi_params 文件需要添加的规则为:
# 以下配置都是为了正确获得 php 的一些全局变量
# 许多 php 框架都需要这些变量来处理路由
fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
这一次配置的最重要的收获是 Nginx 的 location 配置原来是有一定的规则会去影响他的顺序的。location 与后面的 URI 之间的匹配方式有
=
绝对匹配,比如location = /
那就只能匹配首页,这也是效率最好的匹配^~
开头部分匹配,比如location ^~ /sf/
~
或者~*
正则匹配,比如location ~ \.\w+
。~*
是不区分大小写的正则匹配- 无任何符号 部分匹配,比如
location /
匹配任何 uri
匹配的优先顺序就是上面列表的顺序,所以无论把规则 location = /
写在最前还是最后,都会优先执行这条规则的匹配。
有的时候会出现同一个 URI 会同时匹配同一种类型的不同规则的情况,比如上面的配置中 /index.php
这条 uri 既匹配 .php 又匹配 .\w+
,那么这两条规则谁在前面就执行谁的规则。
如果只是测试环境,不用考虑太多性能以及安全问题,配置还能更简单:
server {
set $project_root /path/to/project;
server_name test.localhost;
root $project_root/web;
index index.php;
location ^~ /sf/ {
alias $project_root/lib/vendor/symfony/data/web/sf/;
expires max;
}
location ~ \.php($|\/) {
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
}
location / {
# 尝试处理$uri,不行再处理$uri/
# 还不行再处理/index.php
# 这是nginx官方推荐用来替换
# if (!-f $request_filename) { rewrite ... }
# 的方法
try_files $uri $uri/ /index.php$uri?$args;
}
}
参考资料:
nginx.conf 优化版 (for PHP) by Chris Yue is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.

写作累,服务器还越来越贵
求分担,祝愿好人一生平安
天使打赏人