Nginx不参与vendor路径选择,也不需配置它;核心是禁止Web访问vendor目录并确保PHP-FPM能正确加载其autoload.php——路径必须与Composer实际安装位置严格一致,且权限、用户组需匹配。

vendor 路径由 Composer 安装时决定,Nginx 本身不参与 vendor 路径选择,也不需要“配置”它;你真正要做的,是确保 Nginx 不暴露 vendor 目录,且 PHP-FPM 能正确加载其中的代码。
为什么 Nginx 里不能“配置 vendor 路径”
Nginx 是 Web 服务器,它只负责转发请求(比如通过 fastcgi_pass 把 PHP 请求交给 PHP-FPM),它不解析 PHP、不读取 composer.json、也不决定依赖装在哪。vendor 的位置完全由 Composer 在部署阶段写死——要么是默认的 vendor/,要么是你在 composer.json 里写的 "vendor-dir": "lib/vendor",或环境变量 COMPOSER_VENDOR_DIR 指定的路径。
常见误解是以为加个 alias /vendor /path/to/vendor 就能“切换”,其实这毫无意义:vendor 下的 PHP 文件本就不该被 Web 访问,更不该被 Nginx 直接 serve。
- Nginx 对 vendor 的唯一职责是「禁止访问」,不是「定位」或「挂载」
- PHP-FPM 加载类靠的是
require 'xxx/autoload.php'这行代码,路径必须和 Composer 实际生成的位置严格一致 - 如果你改了 vendor 路径但没同步改
require语句,报错failed to open stream: No such file是必然结果
Nginx 必须加的 vendor 安全拦截规则
哪怕 vendor 路径被你改成 third-party/ 或 deps/,只要它还在 Web 根目录下(比如 /var/www/myapp/third-party/),就必须显式屏蔽。Nginx 默认不会自动识别哪些目录敏感。
在 server 块中加这两段:
location ^~ /vendor/ { return 403; }
location ^~ /third-party/ { return 403; }
注意:^~ 表示前缀匹配且优先级高于正则,比 location /vendor/ 更可靠;别只拦 .php 后缀——composer.json、.env、autoload_static.php 都可能被直接下载。
- 如果用了自定义 vendor 名(如
deps),就得把/deps/也加进拦截列表 -
try_files $uri $uri/ /index.php?$query_string不会阻止对/deps/的访问,它只管路由回退,不负责权限控制 - 别漏掉
/composer.lock和/vendor/composer/下的快照文件,它们含包版本与哈希,泄露即等于暴露攻击面
PHP-FPM 能否加载非默认 vendor 路径?关键看 require 路径是否匹配
PHP-FPM 只关心你代码里怎么写 require。假设你设了 "vendor-dir": "shared/vendor",那么入口文件(如 public/index.php)里必须写:
require __DIR__.'/../shared/vendor/autoload.php';
而不是默认的 ../vendor/autoload.php。否则 PHP-FPM 找不到自动加载器,所有类都报 Class not found。
- 框架如 Laravel 的
artisan或 Symfony 的console通常不直连 vendor 路径,但它们内部仍 require autoload.php —— 路径错,整个 CLI 就瘫痪 - Docker 环境中若用
COMPOSER_VENDOR_DIR,确保该变量在 PHP-FPM 进程启动前注入(例如在www.conf里用env[COMPOSER_VENDOR_DIR]),仅在 shell export 无效 - IDE(如 PHPStorm)可能缓存旧 vendor 路径,导致代码补全失效;需手动刷新 External Libraries 或重新索引项目
生产环境 vendor 权限设置不当的典型报错
即使路径全对、Nginx 拦截到位,vendor 目录权限错误也会让 PHP-FPM 直接失败。常见现象:
-
Warning: require(.../shared/vendor/autoload.php): failed to open stream: Permission denied→ 目录缺执行位(x),PHP 无法进入子目录 -
file_put_contents(/.../vendor/composer/autoload_static.php): Failed to open stream→ 误开了写权限,或文件属主不是 PHP-FPM 运行用户(如www-data) -
Could not scan for classes inside "app/Console"→autoload_static.php权限为600,部署后www-data读不了
正确做法是分层赋权:chmod 755 shared/vendor(目录可遍历),find shared/vendor -type f -exec chmod 644 {} \;(文件只读),再单独 chmod +x shared/vendor/bin/*(仅二进制可执行)。
最易被忽略的一点:确保 PHP-FPM 用户(如 www-data)属于部署用户所在组(如 deploy),否则即使权限是 644,组读权也拿不到。


















