post-update-cmd 在 composer update 或首次 composer install 成功后执行,非每次 require/remove 都触发;需确保真正更新、正确配置 scripts、处理 php 版本与执行上下文,并注意 composer 2.2+ 的双次执行问题。

post-update-cmd 钩子到底在什么时候执行
它只在 composer update(或 composer install 且 vendor/ 不存在时)**成功完成依赖安装后**触发,不是每次 composer require 或 composer remove 都跑——后者只是调用 update 的快捷方式,但钩子仍取决于底层是否真正执行了更新流程。
常见错误现象:post-update-cmd 没反应,其实是你刚 composer install 过、vendor/ 已存在,而 composer require foo/bar 只做了增量修改但没触发完整 update;此时得加 --with-all-dependencies 或直接跑 composer update foo/bar 才能确保钩子运行。
- 钩子不响应
composer dump-autoload或composer clear-cache - 如果
composer.json里没写"scripts"段,或拼错成post-update(缺-cmd),钩子直接被忽略 - 脚本失败(exit code ≠ 0)会导致整个
composer update报错退出,这点常被忽视
怎么写一个可靠的 post-update-cmd 脚本
推荐用 PHP 函数封装逻辑,而不是裸写 shell 命令——前者可复用、易调试、跨平台兼容性好;后者容易因 Windows/Linux 路径或 shell 特性出问题。
示例:在 composer.json 中注册:
"scripts": {
"post-update-cmd": [
"MyScript::buildAssets"
]
}
MyScript 是个类,buildAssets 是静态方法,放在 src/MyScript.php 并已通过 autoload 加载。方法体内可安全调用 exec()、shell_exec() 或原生 PHP 文件操作。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 不要在脚本里写
cd vendor/some-package && npm install—— 工作目录不保证是项目根目录,要用__DIR__ . '/../'或getcwd()显式定位 - 避免硬编码路径如
./node_modules/.bin/webpack;改用vendor/bin/webpack(如果包提供了 bin)或检查which webpack - 若脚本需访问 Composer 内部对象(比如当前 installed packages 列表),可通过
$event->getComposer()获取,但仅限于用Composer\Script\Event参数签名的函数
为什么有时候 post-update-cmd 执行了两次
这是 Composer 2.2+ 的默认行为:它会先以「无插件模式」运行一次钩子(用于基础初始化),再以「全插件加载后」模式运行第二次。如果你的脚本有副作用(比如生成文件、发通知),重复执行就出问题。
解决办法只有两个:
- 升级到 Composer 2.5+,并设置环境变量
COMPOSER_NO_POST_UPDATE_CMD=1(临时禁用)或改用更细粒度的钩子如post-install-cmd+post-update-cmd分离逻辑 - 在脚本开头加判断:
if (getenv('COMPOSER_DEV_MODE') === '1') return;,因为第二次执行时该环境变量通常为1 - 更稳妥的做法:用文件锁或时间戳标记“今日已执行”,避免幂等性陷阱
PHP 版本不一致导致钩子崩溃怎么办
你的项目要求 PHP 8.1,但系统默认 php 是 7.4,而 post-update-cmd 默认用系统 php 解释器执行——结果报 ParseError: syntax error, unexpected token。
必须显式指定 PHP 二进制路径:
"scripts": {
"post-update-cmd": [
"/usr/local/bin/php81 -f scripts/build.php",
"MyScript::onUpdate"
]
}
注意:MyScript::onUpdate 这种写法仍走默认 php,所以混合使用时要小心。另外,Docker 或 CI 环境中,php 路径经常是 /usr/bin/env php,但它可能指向错误版本;建议统一用绝对路径或在 CI 脚本里提前 export PATH=/usr/local/php81/bin:$PATH。
- 别依赖
#!/usr/bin/env php头 —— Composer 不读 shebang -
composer config --global bin-dir设置的路径不影响钩子执行时的 PHP 解释器选择 - 本地开发和 CI 使用不同 PHP 版本时,钩子失败往往最先暴露环境差异,这是好事,别绕过它










