唯一可靠方式是环境变量COMPOSER_VENDOR_DIR,它优先级最高且全命令生效;config.vendor-dir在Composer 2.0+已彻底废弃,仅设环境变量才能真正修改vendor安装路径。

Composer 仓库配置本身不控制包安装路径,真正能改 vendor 目录位置的只有 COMPOSER_VENDOR_DIR 环境变量或(已废弃的)config.vendor-dir;所谓“仓库配置”只是指定从哪下载包,不是决定装到哪。
为什么改 repositories 不会影响 vendor 路径
仓库(repositories)只影响 Composer 查找和拉取包的源头,比如私有 Packagist、Git 地址或本地路径。它完全不参与依赖解压、符号链接生成、autoload.php 写入这些路径敏感操作。
- 你加了
"type": "composer", "url": "https://my-private-repo.com",包还是照常下进vendor/ - 用
"type": "package"手动定义一个本地 ZIP,解压后也默认落在vendor/下对应命名目录 - 即使把所有包都指向
path类型仓库(如"url": "../libs/mylib"),Composer 仍会把它软链或复制进vendor/,除非你额外配installer-paths
想让特定包进自定义目录?用 extra.installer-paths + composer/installers
这是唯一对「某类包」生效的路径控制方式,但前提是包自身声明了匹配的 type,且你已引入安装器插件。
- 先执行:
composer require composer/installers:^2.0(必须 ≥2.0,旧版不支持 Composer 2+) - 在项目根目录
composer.json的extra字段里写:"extra": { "installer-paths": { "third-party/plugins/{$name}/": ["type:wordpress-plugin"], "web/modules/{$name}/": ["type:drupal-module"] } } - 路径值必须是相对路径(不能以
/开头),{$name}是包名最后一段(如wpackagist-plugin/akismet→akismet) - 普通
library类型包(绝大多数 Composer 包)**不会命中任何规则**,它们永远走默认 vendor 路径 - 改完必须删掉整个
vendor/和composer.lock,再跑composer install—— 已安装的包不会被重排
COMPOSER_VENDOR_DIR 是当前最稳的全局路径方案
Composer 2.0+ 彻底废弃 config.vendor-dir,现在唯一全命令生效(install/update/require)的方式就是环境变量。
- 临时生效(推荐测试用):
COMPOSER_VENDOR_DIR=third-party composer install - Linux/macOS 永久生效:加到
~/.zshrc:export COMPOSER_VENDOR_DIR="third-party",然后source ~/.zshrc - Windows PowerShell:
$env:COMPOSER_VENDOR_DIR="third-party" - 路径可以是相对(
third-party)或绝对(/opt/myapp/libs),但避免伪绝对路径(如/third-party) - 注意:这个变量只影响当前项目下的依赖安装,不影响
composer global(它固定走$COMPOSER_HOME/vendor/)
容易被忽略的关键点
无论用 COMPOSER_VENDOR_DIR 还是 installer-paths,以下三件事不做,90% 的报错都源于此:
- PHP 代码里所有
require 'vendor/autoload.php'必须手动改成新路径,比如require 'third-party/autoload.php' -
vendor/bin/下的命令(如phpunit)会变成third-party/bin/phpunit,CI 脚本、IDE 终端 PATH、部署命令全得同步更新 - PHPStorm / VS Code PHP 插件默认只索引
vendor/,必须手动在设置里把新路径加进Include Paths,否则跳转和补全失效


















