Nginx 无法内置识别设备类型,但可通过 map 指令基于 $http_user_agent 预定义 $device_root 变量,在 server 块中统一设置 root $device_root 并同步用于 SCRIPT_FILENAME,确保 PHP 与静态资源路径一致。

如何用 Nginx 的 $http_user_agent 区分设备并重写 root
直接结论:Nginx 本身不内置“手机/PC”判断逻辑,但可通过正则匹配 $http_user_agent 字符串,结合 location 或 if + root 实现目录分流。注意:if 在 server 块中用于修改 root 是可行的,但不能嵌套在 location 内动态改 root(Nginx 会忽略)。
常见错误是写成:
location / {
if ($http_user_agent ~* "Mobile") {
root /var/www/mobile;
}
}
这不会生效——root 在 if 中不被允许重定义。正确做法是提前用 map 预定义变量,或在 server 块顶层用 if + set + root 组合。
推荐方案:用 map 指令预定义 $device_root 变量
map 是最干净、性能最好、且被官方推荐用于此类条件映射的方式。它在 http 块中定义,全局可用,避免 if 的坑。
在 phpEnv 的 Nginx 配置文件(通常是 /phpenv/nginx/conf/nginx.conf 或站点 conf 文件)的 http 块内添加:
map $http_user_agent $device_root {
default "/var/www/pc";
"~*Mobile|Android|iPhone|iPad|iPod|Opera Mini|IEMobile" "/var/www/mobile";
}
然后在你的 server 块中直接使用:
server {
listen 80;
server_name example.com;
root $device_root;
index index.php;
<pre class="brush:php;toolbar:false;">location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $device_root$fastcgi_script_name;
include fastcgi_params;
}}
-
map必须放在http块,不能放server或location - 正则匹配区分大小写,所以用
~*;default对应 PC 端兜底路径 -
SCRIPT_FILENAME必须同步用$device_root,否则 PHP 会找不到.php文件 - 确保
/var/www/mobile和/var/www/pc目录存在且 Nginx 用户(如www-data或nginx)有读取权限
为什么不用 try_files + rewrite?
有人尝试用 try_files /mobile/$uri /pc/$uri =404,这条路走不通。因为 try_files 检查的是物理路径是否存在,而你无法靠路径前缀可靠区分设备——用户可能直接访问 /mobile/style.css,绕过判断逻辑,失去控制权。
更关键的是:try_files 不改变 root,所有请求仍以原始 root 为基准拼接路径,导致 PHP SCRIPT_FILENAME 错误,502 或 404。
所以必须从源头控制 root 和 SCRIPT_FILENAME,而不是靠文件层 fallback。
调试与验证要点
实际部署后容易卡在几个地方:
- 修改配置后必须执行
nginx -t && nginx -s reload,phpEnv 图形界面的“重启 Nginx”有时不生效,建议命令行操作 - 用
curl -H "User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15" http://localhost测试移动端逻辑 - 查看 Nginx error log(
/phpenv/nginx/logs/error.log),常见报错如FastCGI sent in stderr: "Primary script unknown",基本等于SCRIPT_FILENAME路径拼错了 - 手机访问时,浏览器可能启用“桌面版网站”模式,UA 仍是 PC 版,此时会落到 PC 目录——这不是配置问题,是客户端行为,需提醒用户关闭该选项测试
真正麻烦的不是写对正则,而是确保 PHP-FPM 加载的脚本路径和静态资源路径都严格对齐 $device_root。少一个 $device_root 替换,就可能让整个 mobile 站点的 CSS/JS/PHP 全部 404。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











