composer bin-dir 是 composer 安装可执行包(如 phpunit、pest)时指定二进制文件存放路径的项目级配置项,默认为 vendor/bin;修改后旧包不迁移、新包写入新路径,需同步更新 ci、ide、path 等所有依赖该路径的配置。

composer bin-dir 是什么,为什么不能直接改 vendor/bin
它不是“把命令软链接到哪”,而是 Composer 安装可执行包(比如 phpunit、larastan、pest)时,决定把这些二进制文件放在哪的配置项。默认是 vendor/bin,但你改了 bin-dir,Composer 就不会再往 vendor/bin 写,也不会自动帮你迁移旧命令。
- 改完不重装包,旧 bin 文件还在原处,新包却跑到新目录——结果是命令“一半失效”
- 很多 CI 脚本或 IDE 配置硬编码了
vendor/bin/phpunit,换目录后直接报command not found -
bin-dir是项目级配置,对全局 require 的包无效(比如composer global require laravel/installer)
怎么安全地设置 bin-dir:命令行 vs composer.json
两种方式效果一致,但触发时机和适用场景不同。别混用,否则容易冲突。
- 临时改当前项目:运行
composer config bin-dir bin(注意路径是相对 project root 的) - 想让团队/CI 一致:直接编辑
composer.json,加字段"config": { "bin-dir": "tools" } - 绝对路径不推荐——
composer config bin-dir /usr/local/bin看似方便,但会绕过 Composer 的权限管理,且composer install可能因权限失败 - 设为
bin后,记得把./bin加进$PATH,否则 shell 找不到命令
执行 composer install 后 bin 文件没出现?检查这三点
不是配置没生效,而是依赖包本身没声明 bin 字段,或者没触发安装逻辑。
- 确认包的
composer.json里有"bin"键,例如"bin": ["phpunit"];纯库(如symfony/console)不带 bin,不会生成可执行文件 - 运行
composer show --all,看目标包是否在列表中且版本已锁定;如果只是require-dev但当前环境是--no-dev,bin 文件也不会装 - 删掉
vendor/和composer.lock重试——有时 lock 文件残留旧 bin 路径缓存,导致跳过写入
Windows 下 bin-dir 的坑:.bat 和 .php 文件共存
Composer 在 Windows 上会为每个 bin 脚本生成两个文件:phpunit(无后缀,Unix 风格)和 phpunit.bat。Shell 默认优先执行 .bat,但内容只是调用 PHP 解释器跑同名 .php 文件。
- 如果你手动把
bin-dir设成scripts,得确保scripts/在%PATH%里,且顺序靠前;否则可能误调系统 PATH 里的旧版phpunit - 某些杀毒软件会拦截自动生成的
.bat,报“可疑脚本”,需加白名单 - 不要手动删
.bat只留.php——Composer 下次 install 会重建,还可能覆盖你的修改
bin-dir 改动,本质是在改整个项目的命令契约。










