scripts需用composer预定义事件名(如post-install-cmd)或自定义名后手动调用;值可为字符串或数组命令;注意环境变量可用性、退出码处理、路径作用域及并发安全。

composer.json 里 scripts 字段怎么写才生效
scripts 不是随便写个键名就能触发的,必须用 Composer 官方预定义的事件名(比如 post-install-cmd、pre-autoload-dump),或者自定义脚本名后手动调用 composer run。
- 预定义事件会自动在对应生命周期触发,比如
post-autoload-dump在每次composer install或composer update生成自动加载文件后执行 - 自定义脚本名(如
"build": "php build.php")不会自动运行,必须显式执行composer run build(Composer 2.2+)或composer build(旧版) - 脚本值可以是字符串命令,也可以是数组:多个命令会按顺序执行,遇到非零退出码就中断
- 别把脚本名起成和内置命令冲突的,比如叫
install或update,会导致意外覆盖
脚本里访问 Composer 的上下文变量(比如当前包名、版本)
Composer 会在执行 scripts 时注入一组环境变量,以 COMPOSER_ 开头,比如 COMPOSER_ROOT_VERSION、COMPOSER_PACKAGE_NAME,但这些只在部分事件中可用——不是所有脚本都能拿到。
-
pre-autoload-dump和post-autoload-dump能稳定读到COMPOSER_ROOT_PACKAGE和COMPOSER_ROOT_VERSION -
post-install-cmd和post-update-cmd中,COMPOSER_ROOT_PACKAGE可能为空,建议改用getcwd()+ 解析composer.json更可靠 - PHP 脚本里别直接
echo $_ENV['COMPOSER_ROOT_VERSION'],要先getenv()或检查是否存在,否则可能报 Notice - Shell 脚本里可以直接用
$COMPOSER_ROOT_VERSION,但记得加引号防空格:"echo \"$COMPOSER_ROOT_VERSION\""
脚本执行失败却不报错?常见静默退出原因
Composer 默认对 scripts 的非零退出码只警告不中断,尤其在数组形式脚本里,很容易误以为“跑完了”,其实中间某步已失败。
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
- 数组脚本中任意一条命令返回非 0,后续命令不会执行,但整个 script 状态仍是 success(除非加
--no-interaction或设COMPOSER_NO_INTERACTION=1) - PHP 脚本末尾忘了
exit(1),即使逻辑出错也返回 0,Composer 就当它成功 - 用了
&&连接命令(如"php check.php && php build.php")比数组更可控,失败会短路 - 调试时加
-v参数:composer install -v,能看到每条命令的真实 exit code
scripts 调用其他 Composer 命令时的路径与作用域问题
在 scripts 里执行 composer dump-autoload 或 composer run xxx,默认操作的是当前项目根目录的 composer.json,但子目录脚本可能意外污染主 autoload 或依赖解析。
- 避免在子模块的 scripts 里调用全局
composer install,应限定路径:composer --working-dir=./packages/foo install -
composer run在嵌套调用时不会继承父级的--no-dev等标志,需显式传递:"run test -- --no-dev" - PHP 脚本中用
exec('composer ...')启动新进程,无法共享内存或 autoloader,别指望能复用当前脚本里的类实例 - 如果脚本需要修改
vendor/autoload.php行为,优先用autoload-dev+files注册,而不是靠 scripts 动态 patch 文件
scripts 的真正复杂点不在语法,而在事件触发时机与当前工作目录、环境变量、子进程隔离之间的耦合。一个看似简单的 post-update-cmd,在 CI 环境下可能因缓存导致 COMPOSER_ROOT_VERSION 滞后,或因并发安装让 autoload 文件被多进程同时写入——这些都得靠日志和 -v 输出来确认实际发生了什么。










