基于 Nginx + PHP-FPM 作为 HTTP 服务器
引言
PHP 对 HTTP 请求响应支持非常友好,可以通过 PHP 预定义的超全局变量获取 HTTP 请求数据:
$_SERVER
:获取 HTTP 服务器数据$_GET
:获取 URL 查询字符串中的参数(GET 请求参数)$_POST
:获取 POST 请求数据(通常是表单请求)$_FILES
:获取通过 HTTP 上传的文件$_COOKIE
:获取 Cookie 中的数据$_REQUEST
:获取用户请求数据(包含 GET 和 POST 请求以及 Cookie 数据)
所有请求数据都是以关联数组的方式存储在对应的超全局变量中,比如要获取 GET 请求中的 name
参数,可以通过 $_GET['name']
这种方式获取。
下面我们简单介绍下如何在 PHP 代码通过这些超全局变量中获取 HTTP 请求数据。
打印 $_SERVER
内容
PHP 本身不支持通过代码创建 HTTP 服务器,但是可以通过底层 SAPI 接口非常方便的与其他第三方 HTTP 服务器对接,比如 PHP-FPM、Apache、CGI 等。
在 PHP 代码中,可以通过 $_SERVER
获取所有服务器信息,包括 HTTP 请求头、PHP 脚本、服务器环境和系统环境变量等,详细细节可以参考 PHP 官方文档:https://www.php.net/manual/zh/reserved.variables.server.php。
我们在 php_learning
目录下新建 http
子目录,并在该子目录下创建 index.php
保存本篇教程演示代码,我们尝试打印 $_SERVER
变量:
<?php
echo '<pre>';
var_dump($_SERVER);
使用 PHP 内置 HTTP 服务器
接下来在 php_learning/http
目录下启动 PHP 内置服务器:
然后在浏览器中访问 http://localhost:9000
(index.php
是默认首页),就可以看到所有 HTTP 服务器和请求信息:
基于 Nginx + PHP-FPM 作为 HTTP 服务器
不过 PHP 内置 HTTP 服务器只能在本地开发环境使用(性能太差),生产环境可以选择 Apache(需要启用对应的 PHP 支持模块)或者 Nginx + PHP-FPM 组合作为 PHP HTTP 服务器,如果使用 Nginx + PHP-FPM 作为 HTTP 服务器的话,以 Laradock 集成开发环境为例,可以按照如下步骤操作。
注:Nginx + PHP-FPM 组合中,Nginx 是一个反向代理服务器,对于前端静态资源请求直接通过 Nginx 处理,对于后端 PHP 动态请求,会转发给 PHP-FPM 进程处理。关于这一块的更底层原理,可以参考这篇教程了解:基于 Nginx + PHP 驱动 Web 应用(下):请求处理与响应发送篇。
配置 Nginx 虚拟主机
在 laradock
项目根目录下的 nginx/sites
目录下新增一个 php.conf
配置文件配置一个虚拟主机:
server {
listen 80;
server_name php.test;
root /var/www/http;
index index.html index.htm index.php;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
try_files $uri /index.php =404;
fastcgi_pass php-upstream;
fastcgi_index index.php;
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
#fixes timeouts
fastcgi_read_timeout 600;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
location /.well-known/acme-challenge/ {
root /var/www/letsencrypt/;
log_not_found off;
}
error_log /var/log/nginx/php_error.log;
access_log /var/log/nginx/php_access.log;
}
由于这里配置了一个虚拟域名 php.test
,因此需要到本地 /etc/hosts
中添加这个域名映射(Windows 下位于 C:\Windows\system32\drivers\etc\hosts
):
127.0.0.1 php.test
注:如果你想要了解虚拟主机配置中每个配置项的含义,请参考这篇教程:基于 Nginx + PHP 驱动 Web 应用(上):配置文件与虚拟主机篇。
配置目录映射
虚拟主机配置中应用根目录设置的是 /var/www/http
,/var/www
是 workspace
容器中 Web 应用中的根目录,所以我们需要将宿主机中的 php_learning
目录映射到 /var/www
目录,这样,php_learning/http
项目代码才能与 /var/www/http
同步。
要完成这个映射,只需要在 laradock
目录下的 .env
文件中配置 APP_CODE_PATH_HOST
即可:
# Point to the path of your applications code on your host
APP_CODE_PATH_HOST=~/Development/php/php_learning
# Point to where the `APP_CODE_PATH_HOST` should be in the container
APP_CODE_PATH_CONTAINER=/var/www
Windows 系统请自行设置这个目录映射,比如我这里的 php_learning
位于 D:\projects\php\php_learning
,laradock 位于 D:\laradock
,则配置成这样就好了:
APP_CODE_PATH_HOST=../projects/php/php_learning/
这样一来,当我们启动 Nginx + PHP-FPM + Workspace 容器后,在浏览器中访问 http://php.test
时,Nginx 会将 PHP 请求转发给 PHP-FPM 处理,然后 PHP-FPM 会从项目默认入口文件 index.php
开始执行 PHP 脚本代码,从而完成请求分发和处理。
重构 & 启动相关容器
完成以上配置后,需要进入 laradock
目录重构 nginx 镜像:
docker-compose build nginx
然后启动 nginx、php-fpm、workspace 容器 (nginx 依赖后面两个容器,所以会按照依赖关系依次启动):
docker-compose up -d nginx
运行 docker-compose ps
确保所有容器启动成功(State
状态值为 Up
):
访问 PHP 应用
最后,在浏览器通过 http://php.test
即可访问 PHP 脚本 index.php
,这一次信息更丰富,我们只截取部分进行分析:
可以看到 Web 服务器变成了 Nginx,其他的脚本路径也变成了服务器上(Docker 容器)对应的路径和环境变量,请求参数、请求方法、请求头信息也都包含了,还可以从中获取服务端 IP 地址(SERVER_ADDR
)和客户端 IP 地址信息(REMOTE_ADDR
)。
小结
通过 $_SERVER
超全局变量可以获取到所有的 HTTP 请求信息和服务器信息,不过我们在 Web 应用中通常只对 HTTP 请求头和请求数据感兴趣,这些可以通过 $_GET
、$_POST
、$_REQUEST
、$_COOKIE
、$_FILES
等更具体的超全局变量获取,这些我们放到下篇教程去具体介绍。
另外也可以看到,PHP 屏蔽了 HTTP 请求协议的细节,我们不需要对请求头、请求实体、响应头、响应实体等更底层的 HTTP 报文结构进行了解就可以直接通过 PHP 封装的超全局变量获取请求信息,然后直接通过 echo
、var_dump
、print_r
等 PHP 语句和函数或者渲染一个包含 PHP 脚本的 HTML 文档即可将响应实体发送给客户端,非常简单。
No Comments