composer exec 不是 Composer 原生命令,而是由第三方插件提供;官方不支持该命令,正确方式是使用 composer run-script 封装或直接调用 vendor/bin/xxx。

直接用 composer exec 无法在 vendor 目录下执行命令——它根本不是 Composer 原生命令,而是由 composer-execa 或 composer-bin 这类第三方插件提供的功能。
为什么 composer exec 不是原生命令
Composer 官方核心命令列表里没有 exec。你运行 composer exec --help 报错或提示“Command 'exec' is not defined”,说明你本地没装对应插件。常见混淆来源是某些团队文档或 CI 脚本里默认预装了 phpstan/phpstan、dealerdirect/phpcodesniffer-composer-installer 等依赖,它们可能自带封装逻辑,但并非 Composer 自带能力。
真正能跨项目统一执行工具的,是以下两种可靠方式:
- 用
composer run-script配合scripts定义(推荐) - 用
vendor/bin/xxx显式调用(最直白)
正确做法:用 composer run-script 封装命令
在 composer.json 的 scripts 段里定义别名,让 Composer 自动切换到项目根目录(即 vendor 所在位置)再执行:
{
"scripts": {
"phpcs": "php vendor/squizlabs/php_codesniffer/bin/phpcs",
"phpunit": "php vendor/phpunit/phpunit/phpunit"
}
}
然后运行:
composer run-script phpcs -- --standard=PSR12 src/
注意点:
-
--之后的参数会透传给实际命令,不能漏掉 - 路径如
src/是相对于项目根目录的,不是相对于vendor/bin - 所有命令都在项目根目录下执行,天然满足“在
vendor目录下可用”的前提
更简单粗暴:直接调用 vendor/bin/xxx
只要工具支持安装到 vendor/bin/(绝大多数 Composer 包都支持),就不用绕路:
vendor/bin/phpcs --standard=PSR12 src/
vendor/bin/phpunit --testdox
关键细节:
- 确保
vendor/bin在你的$PATH中(开发机建议加进 shell 配置),否则要写全路径 - 某些包不自动注册二进制文件(比如只提供
autoload类库),此时得查文档看是否含 CLI 入口,或改用php vendor/xxx/yyy.php形式 - Windows 下用
vendor\\bin\\phpcs或直接php vendor/bin/phpcs(因 .bat 封装可能失效)
插件方案(仅当团队强依赖时考虑)
如果真需要类似 composer exec phpstan 的语法,可装 roave/composer-dev-bundle 或 consolidation/cgr,但要注意:
- 引入额外维护成本,CI 镜像需同步安装插件
- 不同插件对参数解析行为不一致(比如有的吃掉第一个
--,有的不) -
composer exec插件通常仍会把工作目录设为项目根,不是vendor子目录本身——你并不需要进入vendor/xxx才能运行其命令
真正需要“在 vendor 子目录中执行”的场景极少,多数是误读了错误信息里的路径提示,或者想调试某个包的内部脚本——这时候应该 cd vendor/xxx && php bin/test.php,而不是靠 composer exec 替代。










