Composer 默认将二进制文件软链至 vendor/bin,改用 vendor-bin 需设 "bin-dir": "vendor-bin" 并启用 "bin-compat": "full" 以生成包装脚本而非软链,否则无法生效。

Composer 默认把所有包的二进制文件(如 phpunit、phpcs、larastan)软链到项目根目录的 vendor/bin/ 下,但这个路径容易和开发工具链冲突,也难以区分“谁提供的二进制”——想单独隔离,用 vendor-bin 是可行的,但 Composer 原生不支持该目录名,需手动干预。
vendor-bin 不是 Composer 内置配置项
官方文档中没有 vendor-bin 或类似字段;config.bin-dir 是唯一控制二进制存放位置的配置,它只接受一个字符串路径值,且默认就是 vendor/bin。试图在 composer.json 里写 "bin-dir": "vendor-bin" 会生效,但只是改了软链接目标,并不会让 Composer 自动把包里的 bin/ 目录内容复制或重定向过去——关键点在于:它只影响软链位置,不改变安装逻辑。
所以真要实现“独立存放”,得配合两个动作:改 bin-dir + 禁用软链 + 手动处理 bin 文件。
设置 bin-dir 并禁用自动软链
在 composer.json 的 config 段落中显式声明:
{
"config": {
"bin-dir": "vendor-bin",
"bin-compat": "full"
}
}
bin-compat: full 是重点:它让 Composer 在 Windows 下生成 .bat 包装器,在类 Unix 系统下生成 shell 包装脚本,而不是依赖符号链接。这样即使 vendor-bin 是个干净空目录,也能正常生成可执行入口。
注意:bin-compat: symlink(默认值)在非 Linux/macOS 上可能失败,而 none 会彻底跳过二进制注册——除非你完全不用命令行工具,否则别选 none。
安装后仍看不到 vendor-bin?检查这些地方
- 运行
composer install或composer update后,确认vendor-bin/下是否生成了对应文件(如phpunit);没生成?大概率是某个包没声明bin字段,或你用了--no-scripts -
vendor-bin/必须对当前用户有写权限,否则 Composer 会静默跳过创建(无报错) - 某些 IDE(如 PHPStorm)缓存了
vendor/bin路径,改完配置后需重启或刷新外部工具配置 - 如果你之前运行过
composer install,先删掉旧的vendor/bin/和vendor-bin/,再重新 install,避免残留软链干扰
实际项目中更推荐的替代方案
纯靠 bin-dir 切换目录,治标不治本——它不能解决“多个包提供同名二进制”(如两个不同版本的 phpstan)或“按环境启用不同工具”的问题。更健壮的做法是:
- 用
composer bin(Composer 2.5+)管理多版本二进制:composer bin phpstan install phpstan/phpstan:^1.10,它会在vendor-bin/phpstan/下隔离安装 - 把工具移到
tools/目录,用composer create-project单独拉取,不混入vendor/ - 放弃本地
vendor-bin,改用phive或ghcup等专用二进制分发工具统一管理
真正需要 vendor-bin 的场景其实很少,多数时候只是想避免污染 vendor/bin ——但只要清楚 bin-dir 的作用边界和 bin-compat 的行为差异,就能避开最常踩的“目录建了但没文件”“命令找不到”“Windows 下执行失败”这三类坑。










