Composer自定义脚本需用shell命令形式定义scripts并配合--分隔符透传参数,PHP脚本可用Symfony ArgvInput安全解析,Windows下推荐PowerShell并注意JSON转义。

Composer 自定义脚本本身不支持直接接收命令行参数,但可以通过 -- 分隔符把参数透传给被调用的命令(如 PHP 脚本、Shell 命令)。
composer.json 里怎么写 script 才能接收到参数
必须在 scripts 中定义为 shell 命令或可执行脚本路径,不能是纯 PHP 回调函数(如 "foo": "MyClass::bar"),因为回调函数无法拿到 -- 后的参数。
- ✅ 正确:用
php script.php或sh deploy.sh这类可执行命令形式 - ❌ 错误:用
"build": "App\Scripts\Builder::run"—— 这种写法完全收不到任何外部参数 - 注意:Composer 会原样把
--后面的内容拼接到命令末尾,不做解析
执行时怎么传参:-- 是关键分隔符
不加 --,所有参数都会被 Composer 当作自己的选项处理(比如当成 -v 或 --no-interaction),根本不会透传。
- 正确写法:
composer run build -- --env=prod --force - 错误写法:
composer run build --env=prod→--env=prod被 Composer 拦截,脚本收不到 - 如果脚本是 PHP,它会在
$argv里拿到--env=prod和--force;如果是 Shell 脚本,对应$@
PHP 脚本里怎么安全解析这些参数
别自己手写正则切分 $argv,容易漏掉等号、空格、引号。优先用现成的轻量工具,比如 Symfony 的 ConsoleInputArgvInput(Composer 本身就依赖它)。
- 示例片段(
script.php):use SymfonyComponentConsoleInputArgvInput; $input = new ArgvInput(); $env = $input->getOption('env') ?: 'dev'; $force = $input->hasOption('force'); - ⚠️ 注意:
ArgvInput默认只认--key=value或--key value,不支持短参数如-e prod,除非额外配置 - 如果不想引入依赖,至少用
array_slice($argv, 1)跳过脚本名,再手动遍历,避免直接操作原始$argv
常见坑:Windows 下双横杠失效、JSON 转义、参数含空格
Windows CMD 对 -- 和引号处理更脆弱,PowerShell 表现也不一致;另外 composer.json 里写命令时,JSON 会吃掉反斜杠和引号。
- Windows 用户建议统一用 PowerShell,并确保
composer run xxx -- --message="hello world"中的双引号是英文直角引号 - JSON 里写路径或命令时,反斜杠要写成
\,比如"php .\scripts\deploy.php" - 参数含空格又不想引号?基本做不到 —— 不加引号,Shell 会按空格切词,
--msg=hello world实际变成两个参数:--msg=hello和world
真正麻烦的不是“怎么传”,而是“谁来解析”和“在哪层做边界校验”。很多人卡在脚本里取不到 $argv[1],其实只是忘了 --,或者用了回调式 script 定义。一旦走通透传链路,后面就是常规 CLI 参数解析问题了。










