Nginx配置Yii的核心是:一要location /中用try_files $uri $uri/ /index.php?$args兜住所有非静态请求,二要location ~ \.php$中显式设置fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;,缺一则导致404或502。

直接说结论:Nginx 配置 Yii 的核心就两件事——try_files 把非静态请求兜给 index.php,fastcgi_param SCRIPT_FILENAME 必须写对路径;漏掉任一,404 或 502 就等着你。
location / 块里必须用 try_files $uri $uri/ /index.php?$args
这是 Yii 能跑起来的底线。Nginx 不会自动把 /site/login 这种路由交给 PHP 处理,它只认真实存在的文件或目录。这条规则的意思是:先查有没有对应文件($uri),再查有没有同名目录($uri/),都找不到就内部重写到 /index.php?$args,让 Yii 的 urlManager 接管。
常见错误现象:
- 访问任何页面都返回 404,但
/index.php?r=site/login能进 —— 说明try_files没生效或写错了位置 - 访问
/assets/xxx.js返回 404 —— 可能被后面的location ~ \.php$拦截了,或者root指向不是web/目录
实操建议:
-
root必须指向项目web/子目录,比如root /var/www/myapp/web;,不是项目根目录 - 别在
location /里加if (!-e $request_filename)—— 容易引发循环重定向或 404 - 宝塔用户直接选「Laravel5」伪静态模板,它和 Yii 的
try_files逻辑一致
fastcgi_param SCRIPT_FILENAME 路径必须拼对
PHP-FPM 启动后,Nginx 把请求转过去,但 FPM 不知道该执行哪个文件。如果 SCRIPT_FILENAME 拼出来是空的、错的,或者根本不存在,就会报 502 Bad Gateway 或 “No input file specified”。
关键点:
- 必须显式写
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;,不能只靠include fastcgi_params;—— 因为默认的fastcgi_params里不带这行 -
$document_root的值来自root指令,所以root错了,这里一定错 - Windows 下路径分隔符要用正斜杠
/,别用反斜杠\,否则 PHP-FPM 找不到文件
示例片段:
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass 127.0.0.1:9000;
# 或 fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
}敏感目录和静态资源要分开处理
Yii 的 runtime/、config/、vendor/ 等目录绝对不能被 Web 直接访问,而 web/assets/ 下的 JS/CSS/图片又得缓存。这两类需求得用不同 location 块隔离。
容易踩的坑:
- 没加
location ~ ^/assets/.*\.php$ { deny all; }—— 攻击者可能上传恶意 PHP 文件到 assets 并执行 - 把
expires加在location /里,结果连/index.php都被缓存了 - 用
location ~ \.(js|css|png)$匹配 assets 时,忘了加^/assets/前缀,导致匹配到所有 JS/CSS 文件(包括后台接口返回的 JSON)
推荐写法:
location ^~ /assets/ {
expires 1y;
add_header Cache-Control "public, immutable";
}
location ~ ^/(protected|runtime|config|vendor|nbproject) {
deny all;
}
location ~ /\. {
deny all;
}改完配置一定要 nginx -t 再 nginx -s reload
很多问题其实不是配置逻辑错,而是语法错、路径错、少了个分号,或者 reload 没生效。Nginx 不像 Apache 会自动报错提示,它可能静默失败,继续用旧配置跑。
实操建议:
- 每次改完
nginx.conf或站点 conf,第一反应就是nginx -t—— 它会检查语法+路径是否存在 - 确认输出
nginx: configuration file /etc/nginx/nginx.conf test is successful再 reload - 如果用了宝塔,点「重载配置」前,先去 SSH 执行一遍
nginx -t,避免面板假成功 - 遇到 502,先看
error.log里有没有connect() failed (111: Connection refused)—— 那是 PHP-FPM 根本没起来,不是 Nginx 配置问题
最常被忽略的一点:root 指向的是 web/ 目录,但 runtime/ 和 web/assets/ 的写权限属于 www-data(Ubuntu)或 www(CentOS/宝塔),不是 root。权限不对,Yii 写日志、生成资源都会失败,且错误日志里不一定明说。


















