composer如何使用脚本事件_composer scripts配置详解【自动化】

1次阅读

composer scripts 是 composer 在包生命周期事件中自动触发的钩子机制,本质是 shell 命令或 php 回调的映射表,非任务运行器或 ci 工具;它按「时机 + 命令」配置,不支持流程编排,仅在指定事件(如 post-autoload-dump)中执行,且默认不加载项目 autoloader。

composer如何使用脚本事件_composer scripts配置详解【自动化】

composer scripts 是什么,不是什么

它不是任务运行器(比如 npm run 或 make),也不是 CI 工具;它是 Composer 在安装、更新、卸载包时自动触发的钩子机制,本质是一组 shell 命令或 PHP 回调的映射表。你配的是「时机 + 命令」,不是「流程编排」。

常见错误现象:composer install 没执行你写的 post-install-cmd;或者脚本里用了 phpunit,但本地没装全局,报 Command "phpunit" not found

  • 脚本只在 Composer 自身生命周期事件中触发(如 pre-autoload-dumppost-root-package-install),不会响应 git commit 或文件变化
  • 默认以 shell 方式执行,不自动加载项目 autoloader —— 想调用项目内 PHP 类,得显式 require 或用 php -f
  • 所有命令在项目根目录下运行,路径别写相对 ./src/...,除非你确认上下文

怎么写一个可靠又可复用的 script

核心原则:尽量用 php 调用单文件入口,而不是拼接长 shell 命令。这样可控、可调试、易测试。

示例:你想在 post-autoload-dump 生成 classmap 缓存

"scripts": {   "post-autoload-dump": [     "php -f build/generate-classmap.php"   ] }

而不是:

"scripts": {   "post-autoload-dump": "php -d memory_limit=-1 vendor/bin/classmap-generator --output=vendor/composer/autoload_classmap.php" }
  • 前者把逻辑收口到 build/generate-classmap.php,可以加日志、try/catch、版本判断
  • 后者依赖外部二进制,一旦 vendor/bin/classmap-generator 不存在或权限不对就静默失败
  • 所有 script 命令默认继承 Composer 进程的环境变量,但 $_ENV 不一定包含你期望的值(比如 CI 中的 CI=true)—— 显式传参更稳:"php build/check-env.php --env=prod"

常见事件触发时机与陷阱

不是所有事件都适合干你想干的事。比如想“每次 install 后清空缓存”,用 post-install-cmd 看似合理,但实际它只在 composer install 首次运行时触发,composer install 重跑(无 lock 变更)时根本不会进这个钩子。

  • post-autoload-dump:最常用,autoloader 重建后必走,适合生成代理类、扫描注解、刷新缓存
  • post-root-package-install:仅在 root 包(即你的项目)首次安装时触发,不适合常规自动化
  • pre-update-cmdpost-update-cmd:对应 composer update 全局操作,注意它可能跨多个包更新,别在里面做强依赖单个包的逻辑
  • 事件名大小写敏感:postAutoloadDump ❌,必须是 post-autoload-dump

调试脚本失败的三步法

Composer 不会默认输出脚本 stderr,失败时只报一句 Script ... handling the ... Event returned with Error code 1,非常难定位。

  • -vvv 参数重跑:composer install -vvv,能看到完整命令和输出
  • 在 script 命令前加 set -x;(shell)或 error_reporting(E_ALL); ini_set('display_errors', '1');(PHP),强制暴露执行路径
  • 把 script 改成临时调用一个带 var_dump(getcwd(), $_SERVER['argv']); exit; 的 PHP 文件,确认当前工作目录和参数是否符合预期

最容易被忽略的一点:script 命令里的 &&|| 会让整个链路变成一个 shell 表达式,一旦中间某步非零退出,后续不会执行,但 Composer 仍认为“脚本运行完毕”——它只看最后一条命令的返回值。真要链式执行,拆成数组项,让 Composer 自己串行调用。

text=ZqhQzanResources