Composer插件仅在项目根目录执行composer install/update时由主进程加载激活,包内require无效;需在项目级composer.json中声明并运行install命令才能生效。

Composer插件不会在“包中”被使用——它必须由 Composer 主进程加载,而主进程只在项目根目录运行 composer install 或 composer update 时才扫描并激活插件。 换句话说:你写的一个普通库(比如 myorg/utils)里 require 一个插件,这个插件对它自己毫无作用;只有当这个库被装进某个项目、且该项目执行了 install/update,插件才可能生效。
为什么在包里 require 插件没反应
常见错误是把插件当成普通依赖来用:
- 在
myorg/utils/composer.json的require里写"hirak/prestissimo": "^0.3"—— 这不会让 prestissimo 加速你的包构建过程 - 插件类的
activate()方法根本不会被调用,因为 Composer 不会在解析myorg/utils时启动插件系统 - Composer 插件的生命周期绑定在项目级命令(
install/update/dump-autoload)上,不是包级加载时触发
想让插件影响你的包发布流程?走项目级配置
如果你开发的是一个要打包发布的 PHP 库(如 SDK、工具包),想在 CI/CD 中自动检查代码规范或生成文档,正确做法是:
- 在你的库项目根目录(即含
composer.json的目录)中,把插件加进require-dev,例如:"dealerdirect/phpcodesniffer-composer-installer": "^1.0" - 确保该插件声明了
"type": "composer-plugin"(用composer show dealerdirect/phpcodesniffer-composer-installer看types字段确认) - CI 脚本里必须运行
composer install --no-interaction(不是require),否则插件不注册 - 某些插件还依赖
extra配置,比如指定 PHPCS 标准路径,漏掉就静默失效
本地调试插件时,改了代码却没生效
这是最常卡住的地方:Composer 缓存了 autoloader 和插件实例,文件改了但旧类还在内存里。
- 删掉
vendor/composer/autoload_psr4.php和vendor/composer/autoload_classmap.php - 运行
composer dump-autoload -o强制重建映射 - 必须再跑一次
composer install(不是require),否则activate()不会重入 - 在
activate()里加file_put_contents('/tmp/plugin.log', date('c') . "\n", FILE_APPEND)是唯一靠谱的验证方式
真正容易被忽略的一点:插件是否生效,和它被 require 到哪个包里完全无关;只取决于它是否出现在当前执行 composer 命令的那个项目的 composer.json 中,以及该命令是否触发了插件注册阶段。其他任何位置的 require,都是无效的。


















