默认情况下composer.json脚本不传$event对象,需用静态方法+正确签名(如public static function onPostInstall($event))并配置autoload-dev自动加载,$event为ComposerScriptEvent实例,含getName()、getComposer()、getIO()等关键属性。

Composer脚本里拿不到 event 对象?
默认情况下,composer.json 中定义的脚本(比如 "post-install-cmd")是作为普通 PHP 函数调用的,不自动传入 $event 参数。你写 function myScript($event) 并不会被自动注入——这是最常踩的坑。
必须用闭包或类方法 + 事件监听器注册方式
只有通过 "scripts" 的事件钩子机制注册的、且在 autoload-dev 或运行时可访问的闭包/类方法,才可能拿到 $event 实例。关键是:它得由 Composer 自己调用,而不是你手动执行。
- 在
composer.json中这样写无效:"post-install-cmd": "MyClass::handle"(除非handle是静态且接受一个参数) - 正确姿势是让 Composer 把事件对象传进来,所以函数签名必须是
function ($event),且该函数需能被自动发现 - 推荐做法:在项目根目录放一个
scripts/Installer.php,里面定义public static function onPostInstall($event),然后在composer.json中写:"post-install-cmd": ["scripts\Installer::onPostInstall"] - 注意命名空间和自动加载:确保
scripts/目录已加入"autoload-dev": {"psr-4": {"Scripts\": "scripts/"}}并运行过composer dump-autoload
$event 对象有哪些关键属性
拿到 $event 后,它通常是 ComposerScriptEvent 实例,核心可用字段包括:
-
$event->getName()→ 返回字符串如"post-install-cmd" -
$event->getComposer()→ 获取ComposerComposer实例,可读getPackage()、getInstallationManager()等 -
$event->getIO()→ 获取ComposerIOIOInterface,用于安全地输出/询问(比直接echo强) -
$event->isDevMode()→ 判断是否带--dev运行 - 命令行参数不可直接获取;若需自定义参数(如
composer install --no-interaction --script-param=xxx),得靠环境变量或提前约定配置项(如COMPOSER_SCRIPT_PARAM)
调试时怎么确认 $event 真的进来了
别靠猜。加一行快速验证:
function onPostInstall($event) {
var_dump(get_class($event)); // 应该是 'ComposerScriptEvent'
var_dump($event->getName());
exit(1);
}
如果报错 Missing argument 1 for onPostInstall(),说明 Composer 没传参——检查函数签名、自动加载、composer.json 中的调用写法是否匹配,以及是否用了旧版 Composer(2.0+ 才稳定支持带参调用)。
事件上下文不是“开箱即用”的东西,它依赖正确的注册路径和运行时机;漏掉 autoload 或写错方法签名,$event 就永远是 null 或根本不会被调用。











