post-update-cmd 是 Composer scripts 中预定义的命令别名,非钩子,在 composer update/install 成功后自动执行配置命令,按数组顺序运行,不传递包变更信息、不保证依赖顺序,需正确配置于 composer.json 的 "scripts" 下并避免环境路径等问题。

post-update-cmd 是什么,不是钩子而是命令别名
post-update-cmd 不是 Composer 的“生命周期钩子”,它只是 scripts 配置里一个预定义的命令别名,和 post-install-cmd 一样,本质是 Composer 在执行 composer update(或 install)成功后,自动运行你配置在 scripts 里的对应字段值。它不接收包变更列表、不区分更新/安装、也不保证执行顺序——如果你写了多个 post-update-cmd 值,它们会按数组顺序依次执行,但不会自动去重或做依赖排序。
常见错误现象:post-update-cmd 没执行,或只在 composer install 时跑了一次。原因往往是:你改了 composer.json 但没提交,或者用了 --no-scripts(CI 环境默认可能加这个),又或者脚本本身报错退出导致后续中断(Composer 不会捕获脚本错误并继续)。
- 必须写在
composer.json的"scripts"对象下,键名严格为"post-update-cmd" - 值可以是字符串(单条命令)、字符串数组(多条顺序执行)、或对象(含
"script"和"event"字段的完整定义) - 脚本运行时工作目录是项目根目录,
$COMPOSER_HOME和$PATH可用,但不要假设vendor/bin已加入PATH(有些环境没配)
怎么写才能让 post-update-cmd 真正生效
最简可用写法就是直接写命令字符串。比如生成 autoload 文件、清理缓存、触发类型检查:
"scripts": {
"post-update-cmd": [
"@php vendor/bin/autoload-dump",
"@php -r \"file_put_contents('VERSION', date('Y-m-d H:i:s'));\""
]
}
注意:@php 是 Composer 内置的快捷方式,等价于调用当前 PHP CLI 二进制;如果写 php,得确保系统 PATH 里有且版本匹配。用 @php 更可靠。
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
- 命令前加
@表示调用 Composer 自己的命令别名(如@composer dump-autoload),不加则走 shell 执行 - 如果脚本需要访问 Composer 的内部状态(比如刚更新了哪些包),得用事件监听方式:改用
ScriptEvents::POST_UPDATE_CMD+ 自定义 PHP 类,post-update-cmd字符串模式拿不到这些信息 - 避免在
post-update-cmd里执行耗时操作(如全量测试),它会阻塞composer update返回,CI 中容易超时
常见踩坑:权限、路径、执行时机
错误现象:sh: 1: xxx: not found 或 Permission denied。根本原因不是脚本写错,而是执行上下文缺失。
- Linux/macOS 下,
vendor/bin/xxx脚本第一行是#!/usr/bin/env php,但某些容器或精简环境没装env,或php不在/usr/bin/env路径下——改用@php vendor/bin/xxx绕过 - Windows 用户常遇到
'php' is not recognized:因为composer.json里写的php xxx.php没指定绝对路径,而 Windows 的cmd不像 bash 那样自动查PATH——统一用@php -
post-update-cmd在composer update --lock时也会触发,哪怕没改依赖。如果脚本依赖vendor/下的类,而--lock没重装包,就可能 fatal error ——加file_exists('vendor/autoload.php')判断再执行
替代方案:什么时候不该用 post-update-cmd
如果需求是「每次更新特定包后执行某操作」,post-update-cmd 就不合适。它无法知道哪个包变了,也没有包级过滤能力。这时候该用 Composer 插件或自定义事件监听。
- 想只在升级
monolog/monolog后清日志缓存?得写 PHP 类监听PackageEvents::POST_PACKAGE_INSTALL,再判断包名 - 想把更新结果通知 Slack?用
post-update-cmd可以,但失败时不重试、没日志上下文——更适合放到 CI 流水线的 after-step 里统一处理 - 需要并发安全(比如写同一个文件)?
post-update-cmd是单进程同步执行,但如果你开了多个终端同时composer update,仍可能冲突——加文件锁或用原子写入
真正难的从来不是怎么配这行 JSON,而是想清楚:这个动作到底属于依赖管理流程,还是部署/开发流程。配错位置,后面 debug 花的时间远超写脚本本身。










