composer exec 优先调用 vendor/bin/ 下可执行文件,其次 fallback 到 composer.json 的 scripts;若 vendor/bin/xxx 存在(含 .bat/.sh),则忽略 scripts.xxx,验证方式为删除对应文件后观察报错行为。

composer exec 是 Composer 内置命令,不是插件,也不是别名——它能直接调用 vendor/bin/ 下的可执行文件,也能运行 composer.json 中定义的 scripts 里同名条目,但优先找二进制文件。
怎么判断 composer exec 调用的是 vendor/bin 还是 scripts?
Composer 会按固定顺序查找:
- 先查
vendor/bin/xxx是否存在且可执行(含.bat、.sh或带 shebang 的 PHP 文件) - 找不到才 fallback 到
composer.json的scripts里是否有"xxx": "..." - 如果两者都存在,
vendor/bin/xxx永远胜出——哪怕你写composer exec lint,而vendor/bin/lint是个空文件,它也不会去跑scripts.lint
验证方式:删掉 vendor/bin/phpunit,再运行 composer exec phpunit,就会报错 Command "phpunit" is not defined;但如果只删 vendor/bin/lint,而 scripts.lint 存在,composer exec lint 就能正常跑起来。
为什么有时 composer exec xxx 报 “Command not found”?
这不是 Composer 报错,而是它没在 vendor/bin/ 找到对应文件。常见原因:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
-
composer require --dev xxx/xxx装了包,但该包没在composer.json的"bin"字段声明入口,比如某些工具只提供 PHP 类,不暴露 CLI 二进制 - 装的是全局包:
composer global require phpunit/phpunit→ 它不会出现在本地vendor/bin/,composer exec看不见 -
vendor/bin/目录为空或没生成:没运行过composer install或composer update,或者用了--no-scripts或--no-bin-links - Windows 下
vendor/bin/phpunit.bat权限不对或被杀毒软件拦截,导致不可执行
如何让自定义脚本支持传参(比如 composer exec lint -- src/)?
直接写 "lint": "php-cs-fixer fix" 不行——composer exec lint -- src/ 里的 src/ 不会透传给 php-cs-fixer。必须显式用 $@ 或 %* 接收:
- Linux/macOS:
"lint": "@php vendor/bin/php-cs-fixer fix $@" - Windows(跨平台项目慎用):
"lint": "@php vendor/bin/php-cs-fixer fix %*" - 更稳妥的做法是写一个 shell 包装脚本(如
bin/lint),然后在scripts里调用它:"lint": "bin/lint"
注意:@php 是关键——它绕过系统 PATH 查找 PHP 解释器,避免 Windows 下找不到 .bat 或 Unix 下权限问题;不加它,composer exec lint 在某些 CI 环境可能直接失败。
composer exec 和直接 ./vendor/bin/xxx 有什么实际区别?
核心差异不在“能不能跑”,而在“跑得稳不稳”:
-
./vendor/bin/phpunit是硬路径,Windows 下可能要写成vendor\bin\phpunit.bat,CI 脚本一换平台就挂 -
composer exec phpunit自动选对后缀(.bator.sh),还临时把vendor/bin加进PATH,确保内部调用其他 bin 工具(如phpcs调phpcbf)也不炸 -
composer exec会自动加载vendor/autoload.php,某些依赖 autoloader 的脚本(比如自己写的bin/deploy)不加这步可能 fatal error - 但它不支持完整 TTY,像
psysh或laravel tinker可能卡输入——这种场景老老实实php vendor/bin/psysh
最易被忽略的一点:如果你的脚本本身依赖 $_SERVER['PWD'] 或当前工作目录行为,composer exec 默认在项目根目录运行,而手动执行时容易 cd 错位置,结果路径解析失败。










