在 Nginx 中想要实现以子目录方式配置多个 PHP入口 ,似乎并不是什么很难的问题。以 PHP 动态解释方式运行的语言特性,只要像正常项目一样配置,然后把各个入口目录命名组织好就能达成目的。不过我今天碰到的情况有点特殊,为了解决这个问题着实花了点时间。
首先来看看需求。我有三组不同类型,但属于同一个项目下的 URL。它们分别有各自对应的 PHP 文件入口:
是主域名,它的入口路径为:
/app/frontend/public/index.php
。/api/v1
是后端接口,它的入口路径为:/app/backend/public/index.php
。/file
提供文件服务,它的目录和后端接口相同,但入口文件名不同:/app/backend/public/file.php
。
从入口地址可以看出,这是一个前后端分离的项目。但根据访问路径,分别指向了不同的 PHP 入口路径。由于访问路径和后台文件目录的不对应,所以采用普通的 Nginx + PHP 配置显然无法达到想要的目的。要解决这个问题,只能先从请求路径入手,一个一个来逐一解决。
首先建立一个常规的 Nginx + PHP 配置,来达成第一个默认路径下的访问请求:
server {
listen 80;
server_name www.zzxworld.com;
# 前端接口
location / {
root /app/frontend/public/;
index index.html index.htm index.php;
try_files $uri $uri/ /index.php?$query_string;
location ~ \.php$ {
fastcgi_pass php82-fpm;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
}
第二个后端接口的配置稍微有点烧脑,首先来看看配置好的代码,然后再来解释为什么这里会有点复杂。
# 后端接口
location /api/v1 {
rewrite ^/api/v1/(.*)$ /api/$1 break;
fastcgi_pass php82-fpm;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /app/backend/public/index.php;
fastcgi_param REQUEST_URI $document_uri;
}
上面的配置主要解决了 3 个问题:
- 当访问
/api/v1
路径时,需要改写路径,去掉其中的v1
版本号。这由rewrite
重写指令来完成。 - 指定入口脚本文件的执行路径。这通过
fastcgi_param SCRIPT_FILENAME
配置指令来完成。 - 接口功能使用了 Laravel 框架,为了定位到框架中的路由配置。还需要改写
REQUEST_URI
的值。这通过fastcgi_param REQUEST_URI
来完成。
通过以上三个核心配置,解决了后端接口入口的配置。
最后一个是文件服务入口:
# 文件接口
location /file/ {
alias /app/backend/storage/thumb_files/;
try_files $uri $uri/ @fileGenerator;
}
location @fileGenerator {
fastcgi_pass php82-fpm;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /app/backend/public/file.php;
}
这里通过 alias
指令把 /file/
请求路径映射到了 /app/backend/storage/thumb_files/
目录。然后通过 try_files
来判断请求文件在映射的目录中是否存在。如果存在就直接返回文件内容,如果不存在就转发请求到 @fileGenerator
自定义配置区块,交由 /app/backend/public/file.php
来处理请求。根据这个处理流程可以看出,这是一段支持静态缓存的动态文件生成功能配置。
我在后端接口的配置上浪费了一些时间。原以为这是个很简单的问题,网上搜搜就能找到答案。花时间找了一大堆看似有用,实则不行的 Nginx 配置后,决定还是自己来解决。在理顺了需求,并仔细了解了几个 Nginx 配置指令的作用后,终于顺利解决了问题。说到底还是自己对 Nginx 的配置了解不够深入,今天也算是借此机会加深了对一些 Nginx 配置指令的理解。