zzxworld

PHP 项目中多个子目录入口的 Nginx 配置方式

在 Nginx 中想要实现以子目录方式配置多个 PHP入口 ,似乎并不是什么很难的问题。以 PHP 动态解释方式运行的语言特性,只要像正常项目一样配置,然后把各个入口目录命名组织好就能达成目的。不过我今天碰到的情况有点特殊,为了解决这个问题着实花了点时间。

首先来看看需求。我有三组不同类型,但属于同一个项目下的 URL。它们分别有各自对应的 PHP 文件入口:

  1. http://www.zzxworld.com 是主域名,它的入口路径为:/app/frontend/public/index.php
  2. http://www.zzxworld.com/api/v1 是后端接口,它的入口路径为:/app/backend/public/index.php
  3. http://www.zzxworld.com/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 个问题:

  1. 当访问 /api/v1 路径时,需要改写路径,去掉其中的 v1 版本号。这由 rewrite 重写指令来完成。
  2. 指定入口脚本文件的执行路径。这通过 fastcgi_param SCRIPT_FILENAME 配置指令来完成。
  3. 接口功能使用了 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 配置指令的理解。