真正稳定、值得绑定逻辑的 Composer 生命周期事件只有 post-autoload-dump 和 post-update-cmd;前者每次 install/update 必触发且不依赖 lock 变化,适合生成代理类等轻量操作,但默认不加载项目 autoloader;后者更常用于依赖调整,而 post-install-cmd 仅在 vendor 不存在时触发,故易被误认为失效。

真正稳定、值得你绑定逻辑的 Composer 生命周期事件,只有 post-autoload-dump 和 post-update-cmd 两个。 其他几十个事件名看着多,但要么只在初始化时跑一次,要么每装一个包就触发一次(比如 pre-package-install),极易误判执行时机,调试困难,日常开发中基本不用。
为什么 post-install-cmd 经常不执行?
这不是你写错了脚本,而是 Composer 的行为逻辑决定的:它只在 vendor/ 目录完全不存在时,才走完整安装流程并触发 post-install-cmd。只要 vendor/ 已存在、composer.lock 也没变,Composer 就直接退出,连依赖解析都跳过。
- 验证方法:删掉
vendor/再跑一次composer install,就能看到输出 - 常见误操作:改了
composer.json后直接composer install,结果什么都没发生 - 替代方案:想“每次 install/update 都执行”,一律绑定到
post-autoload-dump——它不看 lock 是否变化,只看 autoload 文件是否重建,而这是 install/update 的必经环节
post-autoload-dump 的实际限制有哪些?
这个事件最可靠,但也最容易踩坑:它默认不加载项目 autoloader,也就是说你在脚本里直接 new 一个自己写的类会报错。
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
- 必须显式
require类文件,或用php -f方式调用独立 PHP 脚本 - 不能依赖
vendor/autoload.php已加载的状态,哪怕脚本就在项目里 - 适合做生成代理类、扫描注解、刷新运行时缓存这类不依赖完整 autoloader 的事
- 如果真要调用项目代码,建议把逻辑抽成 CLI 命令,再在事件里用
php bin/console xxx方式触发
哪些事件只在项目初始化时跑一次?
post-root-package-install 和 post-create-project-cmd 就属于“一生只来一次”的类型,适合模板项目(skeleton)做一次性引导动作。
-
post-root-package-install:在composer create-project过程中,目标包被安装完后触发 -
post-create-project-cmd:整个项目骨架拉下来、vendor/初始化完成后的最后一道钩子 - 典型用途:复制
.env.example到.env、提示用户下一步操作、生成密钥 - 注意:它们不会在后续
composer install或update中再次出现,别指望靠它们做持续维护
真正难处理的不是事件名记不住,而是每个事件的触发条件和上下文隔离程度——比如 pre-autoload-dump 在 classmap 生成前执行,但此时连你自己写的命名空间映射都还没生效;又比如 post-update-cmd 看似好用,但它在 CI 环境下可能因缓存机制导致执行环境不一致。这些细节不试几次根本意识不到。

















