如何设置PHP环境下的Nginx配置,实现二级域名自动匹配子目录?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1038个文字,预计阅读时间需要5分钟。
当然可以,请您提供需要改写的原文内容,我将按照您的要求进行修改。
为什么 server_name ~^(\w+)\.example\.com$ 在 phpEnv 里常失效
phpEnv 的 Nginx 配置通常把多个站点塞进一个 server 块(比如监听 127.0.0.1:80 + server_name _),导致 server_name 正则根本没机会匹配;它只在独立 server 块中生效。实际请求进来时,Nginx 是靠 Host 请求头路由的,所以得从 $http_host 入手。
- 直接写
server_name ~^(\w+)\.local$→ 多数情况下被主配置覆盖,压根不触发 -
$host和$http_host区别:前者是标准化后的 host(小写、无端口),后者是原始 header,更可靠 - 正则里点号必须转义:
\.,否则.匹配任意字符,abc123.local也会被错捕获为abc123l - phpEnv 的 root 路径通常是
/www/wwwroot/,子目录需严格对应文件系统结构,比如/www/wwwroot/blog/
if ($http_host ~* ^([a-z0-9_-]+)\.local$) 提取子域名并设 root
这是最稳的写法,放在 server 块内、location / 外。用 set 把捕获组存成变量,再用于 root 或 alias:
set $subdomain ""; if ($http_host ~* ^([a-z0-9_-]+)\.local$) { set $subdomain $1; } root /www/wwwroot/$subdomain;
- 必须加
if ($subdomain = "") { return 404; },否则访问local或www.local会落到/www/wwwroot//,可能暴露上层目录 - 不推荐用
\w+:它包含大写字母和下划线,但部分 Linux 文件系统对大小写敏感,Blog.local→$subdomain=Blog,而目录名是blog/就 403 -
root拼接后路径末尾不加斜杠,Nginx 会自动补;加了反而可能多出//
PHP 脚本执行时 PATH_INFO 丢失?补 fastcgi_param
子目录下跑 ThinkPHP、Laravel 等框架时,$_SERVER['PATH_INFO'] 常为空,因为 rewrite 后没透传路径。得在 location ~ \.php$ 里显式设置:
立即学习“PHP免费学习笔记(深入)”;
location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /www/wwwroot/$subdomain$fastcgi_script_name; # 关键两行 ↓ fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param SCRIPT_NAME /index.php; include fastcgi_params; }
-
$fastcgi_path_info是 Nginx 内置变量,只有在location用了正则匹配(如~ \.php$)才可用 - 如果框架入口是
public/index.php,root应设为/www/wwwroot/$subdomain/public,否则SCRIPT_FILENAME会指向错位置 - phpEnv 默认的
fastcgi_params不含PATH_INFO,必须手动加;漏掉就只剩$_GET,路由全崩
调试时 curl 怎么验证子域名是否真被识别
别信浏览器地址栏——它不保证发对 Host 头。用 curl -H "Host: api.local" 直连本地 Nginx:
curl -H "Host: api.local" http://127.0.0.1 -I
- 返回
200但内容是 404 页面?说明root拼错了,检查/www/wwwroot/api/是否存在且有index.php - 返回
502 Bad Gateway?PHP-FPM 没监听或fastcgi_pass地址不对,phpEnv 默认是127.0.0.1:9000 - 想看变量值:临时加
return 200 "sub: $subdomain, host: $http_host\n";到 location 里,curl 一眼看清提取结果 -
nginx -t只校验语法,不校验正则逻辑;error_log /var/log/nginx/error.log notice;才能看到运行时变量值
真正卡住的地方往往不是正则写法,而是 phpEnv 的 Nginx 进程没重载配置、子目录权限不对(www 用户不可读)、或者 PATH_INFO 透传漏了一行——这些细节一漏,框架路由就静默失败,查日志都找不到线索。
本文共计1038个文字,预计阅读时间需要5分钟。
当然可以,请您提供需要改写的原文内容,我将按照您的要求进行修改。
为什么 server_name ~^(\w+)\.example\.com$ 在 phpEnv 里常失效
phpEnv 的 Nginx 配置通常把多个站点塞进一个 server 块(比如监听 127.0.0.1:80 + server_name _),导致 server_name 正则根本没机会匹配;它只在独立 server 块中生效。实际请求进来时,Nginx 是靠 Host 请求头路由的,所以得从 $http_host 入手。
- 直接写
server_name ~^(\w+)\.local$→ 多数情况下被主配置覆盖,压根不触发 -
$host和$http_host区别:前者是标准化后的 host(小写、无端口),后者是原始 header,更可靠 - 正则里点号必须转义:
\.,否则.匹配任意字符,abc123.local也会被错捕获为abc123l - phpEnv 的 root 路径通常是
/www/wwwroot/,子目录需严格对应文件系统结构,比如/www/wwwroot/blog/
if ($http_host ~* ^([a-z0-9_-]+)\.local$) 提取子域名并设 root
这是最稳的写法,放在 server 块内、location / 外。用 set 把捕获组存成变量,再用于 root 或 alias:
set $subdomain ""; if ($http_host ~* ^([a-z0-9_-]+)\.local$) { set $subdomain $1; } root /www/wwwroot/$subdomain;
- 必须加
if ($subdomain = "") { return 404; },否则访问local或www.local会落到/www/wwwroot//,可能暴露上层目录 - 不推荐用
\w+:它包含大写字母和下划线,但部分 Linux 文件系统对大小写敏感,Blog.local→$subdomain=Blog,而目录名是blog/就 403 -
root拼接后路径末尾不加斜杠,Nginx 会自动补;加了反而可能多出//
PHP 脚本执行时 PATH_INFO 丢失?补 fastcgi_param
子目录下跑 ThinkPHP、Laravel 等框架时,$_SERVER['PATH_INFO'] 常为空,因为 rewrite 后没透传路径。得在 location ~ \.php$ 里显式设置:
立即学习“PHP免费学习笔记(深入)”;
location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /www/wwwroot/$subdomain$fastcgi_script_name; # 关键两行 ↓ fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param SCRIPT_NAME /index.php; include fastcgi_params; }
-
$fastcgi_path_info是 Nginx 内置变量,只有在location用了正则匹配(如~ \.php$)才可用 - 如果框架入口是
public/index.php,root应设为/www/wwwroot/$subdomain/public,否则SCRIPT_FILENAME会指向错位置 - phpEnv 默认的
fastcgi_params不含PATH_INFO,必须手动加;漏掉就只剩$_GET,路由全崩
调试时 curl 怎么验证子域名是否真被识别
别信浏览器地址栏——它不保证发对 Host 头。用 curl -H "Host: api.local" 直连本地 Nginx:
curl -H "Host: api.local" http://127.0.0.1 -I
- 返回
200但内容是 404 页面?说明root拼错了,检查/www/wwwroot/api/是否存在且有index.php - 返回
502 Bad Gateway?PHP-FPM 没监听或fastcgi_pass地址不对,phpEnv 默认是127.0.0.1:9000 - 想看变量值:临时加
return 200 "sub: $subdomain, host: $http_host\n";到 location 里,curl 一眼看清提取结果 -
nginx -t只校验语法,不校验正则逻辑;error_log /var/log/nginx/error.log notice;才能看到运行时变量值
真正卡住的地方往往不是正则写法,而是 phpEnv 的 Nginx 进程没重载配置、子目录权限不对(www 用户不可读)、或者 PATH_INFO 透传漏了一行——这些细节一漏,框架路由就静默失败,查日志都找不到线索。

