要实现vendor-bin目录隔离,必须使用"config": {"bin-dir": "vendor-bin"}配合"bin-compat": "full",并删除vendor、清缓存、重装依赖,否则仅改配置无效。

别用 composer init 配置 vendor-bin-dir——它根本不支持这个字段,硬写进去也没用。
composer init 不能设 bin-dir,更不存在 vendor-bin-dir
composer init 是个交互式向导,只生成基础 composer.json 结构,不处理 config 里的路径配置。所谓 vendor-bin-dir 并非 Composer 原生字段,是有人把 vendor-bin 插件的目录名和 bin-dir 混写了。实际要隔离工具版本,得靠 bin-dir + composer-bin-plugin,不是靠初始化命令。
-
composer init过程中没有任何选项能设置bin-dir或类似字段 - 手动在
composer.json里加"vendor-bin-dir": "xxx"会被 Composer 忽略,启动时连 warning 都不报 - 真正起作用的是
"config": {"bin-dir": "bin"},且必须配合后续重装依赖才生效
想隔离 phpstan/psalm 等工具?直接上 composer-bin-plugin
全局和项目同名工具打架(比如 phpstan 命令调到旧版),根本解法不是改 bin-dir,而是让每个工具拥有独立 vendor 和 autoload.php。这时 composer-bin-plugin 比手工配 bin-dir 更可靠。
- 运行
composer require --dev bamarni/composer-bin-plugin - 再执行
composer bin phpstan require phpstan/phpstan:^1.12,它会在vendor-bin/phpstan/下建完整隔离环境 - 之后用
./vendor-bin/phpstan/bin/phpstan,完全不碰全局或主vendor - 多个工具互不干扰:一个项目可同时跑
phpstan-1.12和psalm-5.24,各自加载自己的依赖
自己配 bin-dir 的坑:删 vendor、清缓存、手动建目录,一步都不能少
真要用 bin-dir 把脚本挪到 bin/ 目录下,不是改完 composer.json 就完事。90% 的失败都卡在这几步漏掉。
- 必须先删整个
vendor/目录,只删vendor/bin不行——旧链接还在,新bin/里永远空着 - 必须运行
composer clear-cache,否则 Composer 可能从缓存拉旧包,跳过bin-dir重建逻辑 - 目标目录(如
bin/)得提前mkdir bin,且当前用户有写权限;Windows 下若没管理员权限,符号链接会静默 fallback 成 wrapper,但某些工具(如psysh)会因此启动失败 - 改完后
PATH不自动更新,phpunit还是找不到——得自己加export PATH="./bin:$PATH"或坚持用./bin/phpunit
最易被忽略的点:所有这些操作,对已安装的包都不生效。哪怕你把 bin-dir 改成 tools/,只要不重装依赖,vendor/bin 里的旧脚本就继续挂着,新目录始终为空——Composer 不迁移,只新建。











