直接修改 composer.json 的 config.bin-dir 并运行 composer install/update 才生效,项目级配置优先于全局配置,且需手动将 bin 目录加入 PATH 或使用 composer exec。

composer config bin-dir 怎么设才生效
直接改 composer.json 的 config.bin-dir 是最稳妥的方式,但改完必须重新运行 composer install 或 composer update —— 不是改完就立刻迁移文件,旧的还在 vendor/bin,新路径下是空的。
- 项目级配置写在
composer.json根对象里:{ "config": { "bin-dir": "bin" } } - 相对路径(如
"bin"、"scripts/tools")合法;绝对路径(如/usr/local/bin)默认被拒绝,除非加--no-plugins强行绕过,不推荐 -
../开头的路径(如"../tools")会被 Composer 明确报错:The bin-dir value must be relative and not start with ../ - 改完后用
composer config bin-dir验证是否读取成功,再ls -l bin/看文件是否真出现了
全局 bin-dir 和项目 bin-dir 谁说了算
项目配置永远优先于全局配置。哪怕你用 composer config --global bin-dir "vendor/bin" 把全局设成默认值,只要项目 composer.json 里写了 "bin-dir": "tools",那这个项目就只会往 tools/ 里放。
- 全局设置命令:
composer config --global bin-dir "bin"(Linux/macOS)或composer config --global bin-dir "bin"(Windows),实际写入~/.composer/config.json或%APPDATA%\Composer\config.json - 全局配置只对「没声明
bin-dir」的新项目起作用,老项目一升级就按自己规则来 - CI/CD 脚本里别依赖全局配置,显式写
composer install --bin-dir=bin更可控
为什么改了 bin-dir 还是找不到命令
因为 shell 找不到可执行文件——Composer 只负责把脚本放进去,不负责帮你加进 PATH。你得自己告诉系统:“去这儿找命令”。
- 开发时临时生效:
export PATH="$(pwd)/bin:$PATH"(Linux/macOS)或set PATH=%cd%\bin;%PATH%(Windows CMD) - 长期生效:把
export PATH="./bin:$PATH"加到~/.zshrc或~/.bashrc—— 注意:这种写法只在项目根目录下有效;更稳的是用绝对路径,比如export PATH="/path/to/myproject/bin:$PATH" - 替代方案:不用改
PATH,改用composer exec phpunit,它会自动在当前项目的bin-dir下搜索并执行 - Windows 用户注意:
bin-dir设为tools后,Composer 默认复制.bat文件而非创建符号链接,某些杀软会拦截复制动作,导致tools/phpunit.bat缺失
自己的命令怎么进 bin 目录
光配 bin-dir 不够,你还得在 composer.json 里声明 bin 字段,告诉 Composer:“这是我写的 CLI 工具,请把它也放进 bin 目录”。
-
bin字段值是字符串数组,路径相对于项目根目录,例如:"bin": ["bin/mytool", "scripts/deploy.php"]
-
bin/mytool必须有执行权限(chmod +x bin/mytool),且开头带 shebang:#!/usr/bin/env php - 如果脚本是
.php后缀,又想直接mytool运行(不输php mytool.php),就必须加 shebang 并确保有 x 权限;否则只能php bin/mytool.php - 验证方式:
which mytool(已加 PATH)或./bin/mytool --version(直调路径)
bin-dir 看似只是换条路,但路径权限、shell 查找逻辑、Windows 复制行为、项目与全局优先级……每个环节都可能断掉。最容易忽略的是:**改完不重装,等于没改;加了路径不 reload shell,等于白加**。










