改bin-dir不会自动迁移脚本、创建目录或更新PATH,必须手动清缓存、删vendor、建目录并配PATH;合法写法仅限相对路径如"bin"或"./scripts",禁用绝对路径、../开头或$HOME。

改 bin-dir 不会自动迁移已有脚本,也不会创建目录或更新 PATH —— 这三件事都得你手动做,否则 phpunit 依然报 command not found。
composer.json 里怎么写 bin-dir 才合法
必须是相对路径,不能以 /、../ 或盘符开头;也不能用 $HOME(项目级不支持);更不能是绝对路径。
- ✅ 正确:
"bin-dir": "bin"、"bin-dir": "./scripts"、"bin-dir": "tools" - ❌ 错误:
"bin-dir": "/home/user/project/bin"→ 报Invalid bin-dir path - ❌ 错误:
"bin-dir": "../bin"→ 报The bin-dir value must be relative and not start with ../ - ⚠️ 慎用:
"bin-dir": "$HOME/bin"→ 全局配置可能认,但项目级行为不稳定,CI 容易挂
为什么 composer install 后新目录还是空的
因为 bin-dir 只控制「新安装/更新」包的脚本落点,对已存在的 vendor/ 完全无感。旧链接留在 vendor/bin,新目录不会自动生成文件,也不会报错提示你漏了什么。
- 必须先运行
composer clear-cache - 必须删整个
vendor/(不是只删vendor/bin) - 确保目标目录存在且可写:
mkdir -p bin && test -w bin || echo "no write" - 再执行
composer install,这时才会在bin/下生成符号链接(Linux/macOS)或.bat包装器(Windows)
命令敲不进去?大概率是 PATH 没跟上
Composer 从不碰你的环境变量。它把 phpunit 放进 bin/,不代表 shell 就认识这个命令。
- 临时生效:
export PATH="./bin:$PATH"(Linux/macOS)或set PATH=%cd%\bin;%PATH%(Windows CMD) - 长期生效:把
export PATH="./bin:$PATH"加进~/.zshrc或~/.bashrc - 验证是否生效:
echo $PATH | grep bin或where phpunit(Windows) - 替代方案:
composer exec phpunit—— 它会自动识别当前bin-dir并执行,不用配PATH
容易被忽略的 Windows 和插件陷阱
Windows 上不支持符号链接,所以 bin/ 里生成的是 phpunit.bat,不是可直接执行的 phpunit。而某些 IDE 或 shell 补全默认不识别 .bat 后缀,就会显示 “command not found”。
- 路径别含空格或中文,否则
.bat脚本调用 autoload.php 时容易出错 - 如果用了
dealerdirect/phpcodesniffer-composer-installer这类插件,它们可能绕过bin-dir,硬往vendor/bin写 —— 查看插件文档,它往往有自己独立的extra.bin-dir配置项 -
artisan、horizon这类 Laravel 自带命令不受bin-dir影响,它们由框架逻辑控制,和 Composer 的bin字段无关











