post-install-cmd仅在composer install显式执行且lock未变时触发,post-update-cmd仅在update或install--with-dependencies改写lock时触发;autoload相关操作应使用post-autoload-dump。

脚本不生效,八成是钩子名写错、触发条件没满足,或者根本没走对命令流程。
post-install-cmd 和 post-update-cmd 到底谁该跑
这两个钩子名字带 -cmd 后缀,缺一不可;它们不是“安装后就跑”,而是由对应命令显式驱动:
-
post-install-cmd只在composer install显式执行时触发(哪怕 vendor 已存在,只要 lock 没变,它也可能跳过) -
post-update-cmd只在composer update或composer install --with-dependencies真正改写了composer.lock时才触发 -
composer require foo/bar本质是update的快捷方式,所以它只走post-update-cmd,不会触发post-install-cmd - Composer 2.2+ 开始,
post-install-cmd不再被update触发——别再把 autoload 相关逻辑塞进去,否则更新后类加载失败
autoload 文件生成后必须立刻执行的操作,用 post-autoload-dump
post-autoload-dump 是最稳定、最贴近真实依赖变更的钩子:它只在 vendor/autoload.php 或 autoload_psr4.php 这类文件被实际写入后触发,不管你是 install、update 还是 dump-autoload。
- 适合场景:清理框架缓存、生成代理类、调用
My\Project\ComposerScripts::postAutoloadDump这类 PHP 方法 - 注意:
composer install --no-scripts会跳过它;vendor 已存在且 autoload 文件没重写时,它也不会触发 - 别和
post-install-cmd同时写composer dump-autoload—— 重复执行,浪费时间还可能出错 - Windows 下慎用 shell 片段,比如
cp .env.example .env;改用 PHP 脚本或加#!/usr/bin/env php解释器声明
想对某个包做安装后处理?别碰 post-package-install
post-package-install 是实验性钩子,官方明确说“不建议依赖”,而且它根本不会告诉你装的是哪个包:
- 它只在整个
install/update流程结束时触发一次,$event->getOperation()常返回null或不可靠类型 - 缓存命中时可能完全不触发;你
require monolog/monolog,它未必运行 - 真要响应单个包安装(比如 laravel/framework 装完自动生成 config),必须写 Composer 插件,监听
InstallerEvents::POST_PACKAGE_INSTALL事件,并从$event->getOperation()->getPackage()拿实例 - 插件需实现
PluginInterface和EventSubscriberInterface,不能靠scripts配置搞定
手动执行脚本别绕弯,直接用 composer run-script
composer run-script 就是执行 composer.json 里 scripts 字段定义的命令别名,没有时机、不等事件,敲完就跑:
- 比如配了
"build": "php build.php",直接composer run-script build - 支持传参:
composer run-script build -- --env=prod,参数会透传给脚本 - 数组格式定义命令更安全(避免 shell 解析歧义),例如:
["php bin/console cache:clear", "npm run build"] - 别在脚本里嵌套调用
composer install或composer update—— 容易递归卡死,也违反幂等原则
真正容易被忽略的是触发条件的“精确性”:不是写了钩子就等于能跑,而是得同时满足命令行为、文件变更、配置位置、退出码为 0 四个条件。尤其在 CI 环境里,post-update-cmd 因脚本 exit code 非 0 导致整个流程中断,这种问题查起来特别费时间。











