post-package-install 钩子无法按包触发,仅在整体流程结束时调用一次且无包信息;应改用 composer 插件订阅 installerevents::post_package_install 事件,或用 post-autoload-dump 检查目录存在性。

post-package-install 钩子根本不能按包触发
它只在 composer install 或 composer update 整体流程结束时调用一次,且不带任何具体包信息。你配了 "post-package-install" 脚本,指望它对 monolog/monolog 单独执行——这注定失败。
常见错误现象包括:
-
$event->getOperation()返回null,或类型不可靠(比如是InstallOperation但内部 package 字段为空) - 脚本运行了,但拿不到刚装的包名、版本、源路径
- 缓存命中时整个流程跳过,钩子干脆不触发
官方文档已明确标注该事件为 “experimental”,未来可能移除,生产环境不应依赖。
真正捕获“某个包刚装完”的时机:写 Composer 插件
必须实现 Composer\Plugin\PluginInterface 和 Composer\EventDispatcher\EventSubscriberInterface,订阅底层事件 Composer\Installer\InstallerEvents::POST_PACKAGE_INSTALL(注意不是字符串 "post-package-install")。
关键点:
- 插件需声明
"type": "composer-plugin",并被根项目require(不能只放autoload) -
$event->getOperation()->getPackage()才能稳定拿到PackageInterface实例,含名称、版本、源类型等完整信息 - 适合场景:为
laravel/framework自动生成配置;给drush/drush注册 bin;对私有包解密资源文件
别试图用 scripts 模拟——它没有包上下文,也进不了安装器生命周期。
想绕过插件开发?改用 post-autoload-dump + 显式判断
如果只是需要“某包存在就做点事”,且能接受延迟到 autoload 生成后执行,post-autoload-dump 是更轻量的选择。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
它每次 composer install、update 或 dump-autoload 都会触发,且保证 vendor/autoload.php 已就绪。你可以手动检查包目录是否存在:
php -r "
if (is_dir('vendor/monolog/monolog')) {
file_put_contents('runtime/monolog-installed', date('c'));
}"
优势:
- 不用写插件、不用注册类型、不增加依赖树复杂度
- 兼容所有 Composer 2.x 版本
- 可配合
composer dump-autoload --no-scripts精确控制触发时机
缺点:无法区分“是这次装的”还是“早就有的”,也不提供版本变更通知。
强制重装单个包 ≠ 触发钩子,而是重建文件系统状态
插件或脚本能生效的前提,是包真被重新解压进 vendor/。而 composer install 默认跳过已存在目录——哪怕里面文件已损坏。
确保钩子逻辑被触发的实操路径只有两条:
- 删掉对应目录再
composer install:rm -rf vendor/guzzlehttp/guzzle && composer install - 或用
composer install --force-reinstall(它会对 lock 中每个包执行卸载+重装,包括运行post-install-cmd)
注意:--force-reinstall 不清缓存,若怀疑 ZIP 本身损坏,必须先 composer clear-cache 再加 --no-cache。
最易忽略的一点:插件监听的是安装器事件,不是脚本事件;它不关心你有没有配 post-install-cmd,只响应底层 InstallerEvent 的分发。没写对接口、没正确订阅、没放进 vendor 加载链,就等于没挂上。










