Composer脚本无法直接接收命令行参数,需通过$argv手动解析透传参数;$argv[0]为脚本路径,$argv[1]起为用户传入参数如--env=prod。

Composer脚本里根本不能直接接收命令行参数
这是最常被误解的一点:你运行 composer run-script deploy -- --env=prod,那个 -- --env=prod 看似像传参,但默认情况下,deploy 脚本函数(比如 PHP 回调)根本收不到 --env=prod。Composer 会把 -- 后面的内容原样透传给执行器(如 PHP CLI),但不会自动解析或注入到你的回调函数参数里。
用 $argv 手动读取透传的参数
Composer 在调用 PHP 脚本时,会把整个命令行参数数组传给 PHP 进程,所以你在脚本中可以用 $argv 拿到所有内容,包括 --env=prod 这类透传项。关键是要知道它从哪一位开始出现——通常 $argv[0] 是脚本路径,$argv[1] 开始才是你传的参数。
- 在
composer.json中定义脚本:"scripts": { "deploy": "php scripts/deploy.php" } - 在
scripts/deploy.php中解析:<?php array_shift($argv); // 去掉脚本名 $options = []; foreach ($argv as $arg) { if (str_starts_with($arg, '--env=')) { $options['env'] = substr($arg, 6); } } echo "Deploying to env: " . ($options['env'] ?? 'dev') . "\n"; - 调用方式必须带
--分隔符:composer run-script deploy -- --env=staging
别用 static function 回调——它不支持参数透传
如果你在 composer.json 里写的是 "deploy": "MyScript::run" 这种静态方法回调,那恭喜,$argv 不可用,且 Composer 绝对不会把任何参数塞进 run() 的函数签名里。这种写法是单向、无参的,连 -- 后面的东西都进不了进程。
- ❌ 错误示例:
"scripts": { "build": "BuildTool::compile" }——compile()函数签名哪怕写成public static function compile($env = 'dev'),也永远不会收到值 - ✅ 正确做法:改用可执行脚本(PHP 文件、Shell 脚本),或封装一层 CLI 入口,靠
$argv或getopt()解析 - 注意:即使你用
exec或shell_exec在回调里再起一个 PHP 进程,也得手动拼$argv,别指望 Composer 替你转发
环境变量比命令行参数更可靠
如果只是想区分环境、开关行为,用环境变量比折腾 --xxx 更稳定。Composer 会继承父 shell 的环境变量,PHP 脚本里直接 getenv('APP_ENV') 就行,不用处理分隔符、引号转义、空格截断等问题。
- 运行时设置:
APP_ENV=prod composer run-script deploy - 脚本内获取:
$env = getenv('APP_ENV') ?: 'dev'; - 适合 CI 场景:GitHub Actions、GitLab CI 天然支持环境变量注入,比维护一堆
--参数更不易出错 - 唯一限制:不能在同一个
composer run-script命令里混用多组不同参数(比如同时指定--env和--force),这时还是得回到$argv解析
命令行参数透传这事,表面是“怎么传”,实际是“谁来解析”——Composer 只负责启动进程,不负责解包。最容易卡住的地方,就是以为写了 --foo=bar 就能自动进函数参数,结果 var_dump($argv) 一看才发现它压根没出现在数组里,只是被 shell 吃掉了。


















