Composer事件监听实战:如何在post-install-cmd中触发自定义逻辑?

10次阅读

post-install-cmd仅在vendor为空或被清空时触发,非每次install都执行;定义方式优先内联PHP,其次外部PHP文件,最后shell;回调中需判空$event->getcomposer()并用getcwd()获取根目录。

Composer事件监听实战:如何在post-install-cmd中触发自定义逻辑?

可以直接在 composer.json"scripts" 字段里定义 post-install-cmd 对应的命令,但要注意:它只在 composer installvendor/ 为空或被清空时触发,不是每次安装都执行。

post-install-cmd 触发条件和常见误判

很多人以为只要运行 composer install 就会触发 post-install-cmd,其实不然:

  • 如果 vendor/ 已存在且 composer.lock 未变更,Composer 会跳过安装依赖,也跳过该事件
  • 使用 --no-scripts 参数会直接禁用所有脚本,包括这个
  • composer update 不会触发 post-install-cmd,它走的是 post-update-cmd
  • CI 环境中若提前缓存了 vendor/,本地开发没问题,CI 却不执行——这是最常被忽略的部署陷阱

定义自定义命令的三种方式

推荐按优先级排序:先尝试内联 php 脚本,再考虑外部脚本,最后才用 shell 命令(跨平台兼容性差)。

  • 内联 PHP:适合轻量逻辑,无需额外文件,自动继承 Composer 的 autoloader
  • 外部 PHP 文件:适合复用逻辑,需确保路径正确(建议用 __DIR__$argv[0] 定位)
  • Shell 命令:仅限简单文件操作,windows 下容易出错,php -r 比直接写 echo 更可靠
{     "scripts": {         "post-install-cmd": [             "@php -r "file_put_contents('install.stamp', date('c'));"",             "app\ComposerScripts::onPostInstall"         ]     } }

在 PHP 回调中安全访问 Composer 实例

自定义静态方法(如 AppComposerScripts::onPostInstall)接收两个参数:$EventComposerScriptEvent 实例)和可选的 $ioComposerIOIOInterface)。关键点:

  • 不要假设 $event->getComposer() 总是可用——某些早期阶段可能为 NULL,需判空
  • 获取项目根目录用 $event->getComposer()->getConfig()->get('vendor-dir') 不可靠,应改用 $event->getComposer()->getPackage()->getAutoload()['psr-4'] 或更稳妥的 getcwd()
  • 若需加载项目类,别手动 require,用 $event->getComposer()->getAutoloadGenerator()->getStaticFile() 找 autoload.php 路径

调试脚本不执行的最快办法

--verbose 是第一步,但真正有效的是组合使用:

  • --no-plugins 排除第三方插件干扰
  • 临时删掉 vendor/composer.lock,再跑 composer install --dry-run 看是否列出你的脚本
  • 在回调开头加 file_put_contents('/tmp/composer-debug.log', print_r($event, true), FILE_APPEND);,确认是否进来了
  • 检查 composer.json 是否有语法错误:运行 composer validate --no-check-publish

最隐蔽的问题是 autoload 配置缺失导致类找不到——哪怕只是 echo 一句,也要确保 autoloadautoload-dev 里声明了对应命名空间

text=ZqhQzanResources