bin-dir 配置改的是依赖包提供的可执行文件的安装目录;它只影响 vendor 中依赖包的 bin 文件被链接或复制到何处,不改变 vendor 位置,也不影响自定义脚本调用,需配合 composer.json 的 bin 字段声明及重装生效。

bin-dir 配置改的是谁的二进制目录?
它只影响当前项目里所有依赖包(如 phpunit/phpunit、laravel/installer)提供的可执行文件(CLI 工具)被链接或复制到哪,**不改变 vendor 目录位置,也不影响你自己的脚本是否能被调用**。你项目自己写的命令行工具,得靠 bin 字段声明,再配合 bin-dir 一起生效。
-
bin-dir是“安装目标”,不是“源路径”——它不管脚本在哪写,只管最后放哪 - 设成
"bin-dir": "tools"后,vendor/bin/phpunit不再存在,取而代之是tools/phpunit - 依赖包内部硬编码的
../vendor/autoload.php路径不受影响,该找哪还找哪
怎么配才真正生效?三步缺一不可
改了 composer.json 里的 config.bin-dir,不代表立刻就变。Composer 不会热重载配置,必须触发重安装逻辑。
- 在
composer.json的config段加上:{ "config": { "bin-dir": "scripts" } } - 删掉旧的符号链接:运行
rm -rf vendor/bin(Windows 用rmdir /s vendor\bin) - 重新执行
composer install或composer update—— 只有这时才会把所有 bin 文件挪到scripts/下
为什么改了 bin-dir 还是找不到命令?PATH 和权限问题最常见
就算 scripts/phpunit 已生成,终端直接敲 phpunit 还是报 command not found,大概率是环境没跟上。
- Linux/macOS:需手动加进 shell 的
PATH,比如在~/.zshrc里加一行:export PATH="./scripts:$PATH" - Windows:要把
%CD%\scripts加进系统或用户级PATH环境变量(注意是当前项目路径) - 权限问题:Linux/macOS 下
chmod +x scripts/*必须做,否则即使路径对也提示Permission denied - 别信
composer exec phpunit能绕过 PATH —— 它只是帮你找,但不会自动修复执行权限
全局配置 vs 项目配置,哪个优先?
项目级 bin-dir 永远压倒全局设置,这是 Composer 明确规定的优先级规则,不是“建议”。
- 全局设了:
composer config --global bin-dir "/usr/local/composer-bin" - 但只要项目
composer.json里写了"bin-dir": "bin",那这个项目就一定用bin/,全局配置完全失效 - 临时覆盖可用:
composer install --bin-dir=dev-tools,但只作用于当次命令 - CI/CD 中慎用全局配置——很多构建镜像根本不读
~/.composer/config.json,只认项目内配置
真正容易被忽略的点:改完 bin-dir 后,vendor/bin 目录本身并不会消失,它只是不再被更新;如果之前有其他插件(比如 hirak/prestissimo 旧版)或自定义脚本往里塞东西,那些残留文件还会留着,造成混淆。










