config.vendor-dir 是唯一可靠方式,需在项目根目录 composer.json 的 config 字段下用相对路径配置(如 "third-party"),且必须删除旧 vendor 后运行 install;其他方法在 Composer 2.x 中均失效或被忽略。

config.vendor-dir 是唯一可靠方式
想把 vendor 换成 third-party 或 libs,只能在项目根目录的 composer.json 里写 "config": {"vendor-dir": "third-party"}。其他方法——比如 COMPOSER_VENDOR_DIR 环境变量、composer install -d 参数、全局 config.json——在 Composer 2.x 中全部失效或静默忽略。
必须同时满足三个条件才生效:
- 配置写在
composer.json最外层的config字段下,不能错放到extra或缩进错误 - 值必须是相对路径(如
"third-party"),不能以/开头,也不支持$HOME或通配符 - 运行
composer install前,旧vendor目录必须已删除;composer update不会迁移已有包
改完 vendor-dir 后 autoload.php 路径必须手动同步
vendor/autoload.php 是硬编码路径的引导文件,改了 vendor-dir 后它不会自动重写。你删掉旧 vendor、跑完 install,新入口实际在 third-party/autoload.php,但所有 PHP 文件里写的 require 'vendor/autoload.php' 还是会报错。
需要人工处理这些引用点:
- 项目入口文件(如
index.php、cli.php)里的require语句要改成require 'third-party/autoload.php' - IDE(如 PHPStorm)需在
Settings → PHP → Include Paths中添加新路径,否则无法跳转和补全 - CI/CD 脚本、部署命令中所有硬编码的
vendor/bin/phpunit或vendor/autoload.php都得同步更新
bin-dir 必须和 vendor-dir 一起配,否则命令链断裂
很多包(如 phpunit、laravel-zero)在自己的 composer.json 中声明了 "bin" 字段,Composer 默认把二进制文件软链接到 vendor/bin/。只改 vendor-dir 不动 bin-dir,链接就指向不存在的位置。
正确做法是在同一 config 块里显式配齐:
"config": {
"vendor-dir": "third-party",
"bin-dir": "third-party/bin"
}
注意:
- 如果用了
composer create-project,首次安装可能忽略bin-dir,装完务必检查third-party/bin/下是否存在对应文件 -
bin-dir值必须是相对于项目根的路径,且必须匹配vendor-dir下的子目录结构 - CI 脚本中调用的
./vendor/bin/phpunit必须同步改为./third-party/bin/phpunit
installer-paths 不是通用路径重定向,别指望它改普通库位置
看到 extra.installer-paths 就以为能按包名把 monolog/monolog 单独挪到 libs/monolog?不行。它只对声明了特定 type(如 "type": "wordpress-plugin")且项目已引入对应 installer(如 composer/installers)的包生效。
普通库(type: library)哪怕写进 installer-paths 规则,也照旧进 vendor(或你配的 vendor-dir)。这是最常被踩的坑。
真要用 installer-paths,必须确认三点:
- 目标包的
composer.json明确写了"type": "xxx" - 你的项目已执行
composer require composer/installers - 整个
vendor(或vendor-dir)已被删干净,再跑composer install
路径中 {$name} 是占位符,会被替换成包名最后一段(如 acme/my-plugin → my-plugin),且路径必须相对于项目根,不能以 / 开头。
真正麻烦的不是改路径本身,而是所有依赖它的环节:autoload 引用、bin 调用、IDE 索引、CI 脚本、甚至 Docker 构建上下文中的 COPY 指令——它们都得跟着动。漏掉任意一处,就会在某个环境里突然报 Class not found 或 command not found。











