composer run-script 默认不透传 -- 后参数,必须在脚本定义中显式处理或改用环境变量、composer exec 等可靠方案。

Composer run-script 传参时 -- 后面的参数去哪了
直接说结论:composer run-script 默认不会把 -- 后的参数自动透传给脚本,必须显式声明 --no-interaction 或在脚本定义中启用 pass-through 行为——但 Composer 原生不支持自动透传,所谓“追加参数”其实是靠 shell 层级拼接实现的。
scripts 中定义脚本时如何接收外部参数
Composer 的 scripts 是以字符串形式存储的命令,它本身不解析参数。真正起作用的是你写的那个命令(比如 PHP 脚本、Shell 命令或 php myscript.php),而 composer run-script 只负责执行这个字符串。
- 如果你写的是
"test": "php tests/run.php",那么composer run-script test -- --verbose中的--verbose不会到达run.php,因为中间没有透传机制 - 正确做法是改写为
"test": "php tests/run.php --verbose",或更通用的"test": "php tests/run.php @phpscript-args"(但需自行解析) - 想动态传参?只能用
env变量 +$_SERVER或getenv():运行时设SCRIPT_ARGS="--verbose --filter=testFoo" composer run-script test,脚本里读取getenv('SCRIPT_ARGS')
为什么 composer run-script xxx -- --foo 看似有效但不可靠
某些情况下你发现 --foo 确实被收到了,这通常是因为你调用的底层命令(如 phpunit、php-cs-fixer)自身支持 -- 分隔符,并且 Composer 在执行时恰好把整个命令行原样交给 shell——但这属于巧合,不是 Composer 的设计行为。
-
composer run-script fix -- --dry-run能生效,是因为"fix": "php-cs-fixer fix"这条命令被 shell 执行为php-cs-fixer fix --dry-run,本质是 shell 的参数拼接,不是 Composer 解析了-- - 换成
"fix": "php fixer.php"就完全失效,因为php解释器不识别--dry-run,会报错Unknown option --dry-run - Windows 下尤其容易失败:cmd 对
--后参数处理更严格,常直接截断或报语法错误
安全可靠的参数传递方案
别依赖 -- 自动透传。真实项目里推荐这三种方式:
- 用环境变量:运行前设
MY_ARG="--verbose --group=unit" composer run-script test,PHP 脚本里用$argv = array_merge($_SERVER['argv'], explode(' ', getenv('MY_ARG') ?: '')); - 改用
composer exec(Composer 2.2+):composer exec -- php tests/run.php --verbose,它就是直连 shell,参数天然透传 - 封装一层 thin wrapper:在
scripts里写"test": "php -r \"include 'tests/run.php';\" --",再让run.php手动解析$argv,注意--之后才是用户参数
最易忽略的一点:所有这些方案都要求你在脚本里手动 array_shift($argv) 多次来跳过 php、脚本路径、-- 等前置项——不清理就直接用 $argv[1],大概率拿到的是 run.php 而不是你想要的 --verbose。











