Composer 1.10+/2.0+ 支持 pre-install-cmd,但需满足三条件:版本达标、未禁用脚本(--no-scripts)、scripts 为顶层字段;它在 install 初期执行,vendor/ 可能为空且不可加载 autoload;pre-autoload-dump 才适合生成 stub 或修改 classmap。

Composer 没有 pre-install-cmd 之外的“安装前钩子”可直接替代,但你真正需要的不是名字,而是**在依赖解析开始前执行逻辑的能力**——这个能力从 Composer 1.10 和 2.0 起已稳定可用,前提是配置正确、版本达标、未禁用脚本。
pre-install-cmd 真的能用吗?看三个硬条件
很多人配了却没触发,不是钩子失效,而是卡在基础前提上:
-
composer --version必须 ≥ 1.10 或 ≥ 2.0;旧版(如 1.9.x)压根不识别该事件名 - 命令行不能带
--no-scripts,哪怕只是 CI 脚本里漏写了一个 flag,整个 scripts 段都会被跳过 -
composer.json中的"scripts"必须是顶层字段,不能嵌套在"extra"或其他位置
验证是否生效:加一条 @php -r "echo '[pre-install] OK\n';",运行 composer install --no-interaction,看到输出才算通过第一关。
pre-install-cmd 和 pre-update-cmd 的行为差异
二者触发时机高度相似,但关键区别影响你的逻辑设计:
-
pre-install-cmd在composer install启动时立即执行,此时vendor/可能为空或不完整,composer.lock必须存在 -
pre-update-cmd在composer update启动时执行,此时composer.lock将被重写,适合做“更新前快照”或“兼容性检查” - 两者都**无法加载
vendor/autoload.php** —— 因为 autoload 文件还没生成,任何new SomeClass()或class_exists()都会 fatal error
示例场景:你想在 install 前校验环境变量。用 pre-install-cmd 是对的;但若想在 update 前比对当前依赖与新版本的 PHP 扩展要求,就得用 pre-update-cmd 并手动解析 composer.json 和锁文件。
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
pre-autoload-dump:唯一能安全操作 autoload 生成前的钩子
如果你的任务是“生成 stub 类”“动态修改 autoload classmap”或“清理旧生成文件”,pre-autoload-dump 是唯一正解,但它和 install/update 前逻辑有本质错位:
- 它在依赖下载、解包完成后才触发,但早于
vendor/autoload.php写入 —— 此时vendor/已就位,但自动加载器尚未激活 - 你可以安全
require 'scripts/generate-stub.php',只要这个脚本不依赖vendor/autoload.php或第三方类 - 不能调用
composer dump-autoload自身,否则会递归触发,导致无限循环 - 常见误用:把数据库迁移或密钥生成放在这里 —— 它们该由
post-install-cmd处理,因为那时 autoloader 已可用
典型安全操作:file_put_contents('vendor/composer/stubs/MyStub.php', "<?php ...");,后续会被 classmap 自动收录。
为什么 post-install-cmd 不适合“预处理”?
名字带“post”,但它实际触发时间点常被误解:
-
post-install-cmd**只在非首次 install 时触发**:即vendor/autoload.php已存在的情况下才会跑;首次composer install时它完全静默 -
post-update-cmd则每次update都触发,但已是所有包下载、安装、autoload 生成完毕之后 —— 此时再做“检查环境”或“中断流程”为时已晚 - 试图用
post-install-cmd+exit(1)来模拟预校验,结果只会让 install 成功但后续脚本失败,状态不一致
真正的预处理必须发生在“决策之前”,而不是“尘埃落定之后”。这也是为什么 pre-install-cmd 和 pre-update-cmd 不可替代——它们是你阻止错误进入 vendor 的最后一道闸门,而闸门一旦打开,就再没回头路。


















