唯一稳当方式是提前在composer.json中配置"config": {"vendor-dir": "xxx"},并删旧vendor和composer.lock后重装;-d参数只改变读取起点,不改变vendor写入路径。

不能靠命令行参数或项目级配置直接改 vendor 目录位置,唯一稳当方式是提前在 composer.json 里写死 "config": {"vendor-dir": "xxx"},且必须删掉现有 vendor 和 composer.lock 后重装。
为什么 composer install -d /path 不会改变安装路径
-d 参数只影响 Composer 去哪找 composer.json 和 composer.lock,它等价于先 cd /path 再执行 composer install。vendor 还是照常写进该目录下的 vendor/(或已配置的 vendor-dir)。CI 脚本里滥用这个参数,结果就是本地跑通、线上报 Class not found——因为 PHP 还在加载旧路径的 autoload.php。
- 它不改写入目标,只改读取起点
- 想换路径,必须提前在目标项目的
composer.json中配置config.vendor-dir - 改完后,
require 'vendor/autoload.php'这类代码要同步改成新路径,比如require 'third-party/autoload.php'
改了 vendor-dir 但 autoload.php 报错怎么办
因为 vendor/autoload.php 是生成时硬编码路径的入口文件。你改了 vendor-dir,但没重建整个 vendor 结构,旧文件还在原地,PHP 还在找原来的路径。
-
composer dump-autoload不够——它只刷新类映射,不重建入口文件和符号链接 - 必须删掉整个
vendor目录 +composer.lock,再执行composer install - IDE(如 PHPStorm)默认只索引
vendor,需手动在 Settings → PHP → Include Paths 中添加新路径 - 如果用了
bin-dir,也得同步配,例如:"bin-dir": "third-party/bin",否则phpunit等命令会断链
installer-paths 配置写了却没生效的常见原因
这个机制不是全局挪 vendor,而是按包类型把特定包(如 WordPress 插件)装到指定子目录,但它有三个硬性前提缺一不可:
- 项目已运行过
composer require composer/installers(版本 ≥ 2.0) - 目标包自身的
composer.json中声明了匹配的"type"(如"type": "wordpress-plugin"),普通library类型完全不触发 - 必须删掉整个
vendor和composer.lock,再跑composer install——它不会重排已有包 - 路径中
{$name}是占位符,会被替换成包名最后一段(如acme/my-plugin→my-plugin),路径必须相对于项目根目录,不能以/开头
想让所有项目共用一个 vendor 目录,能行吗
可以,但要用 COMPOSER_HOME + 全局 config.json,而不是改项目 composer.json。因为 vendor-dir 是 Composer 的运行时配置项,只在全局或系统级配置中被读取,项目级 composer.json 中的 config.vendor-dir 会被忽略。
- 先设环境变量:
export COMPOSER_HOME="/opt/my-composer-home"(Linux/macOS)或setx COMPOSER_HOME "D:\my-composer"(Windows) - 再在
$COMPOSER_HOME/config.json里写:{"config": {"vendor-dir":"/opt/shared-vendor"}} - 注意:旧
auth.json、缓存、全局包都要手动迁移过去,否则静默失败 - 不推荐用于生产部署——多个项目共享 vendor 容易因版本冲突或 autoload 映射重叠导致不可预知行为
最常被忽略的一点:无论用哪种方式改路径,vendor/autoload.php 的路径是生成时写死的,任何后续配置变更都不会自动更新它;必须彻底重建 vendor 才算真正生效。别跳过删 lock 这步,否则所有配置都只是幻觉。


















