composer插件必须实现plugininterface并声明type: composer-plugin,否则不会被加载;需在post-install-cmd或post-update-cmd中安全清理缓存,避免误删vendor内正在构建的文件。

Composer插件必须实现PluginInterface才能被识别
Composer不接受任意PHP类作为插件,只有实现了ComposerPluginPluginInterface的类,且在composer.json中正确声明type: composer-plugin,才会在composer install或update时被自动加载。漏掉任一条件,插件就完全不会触发。
常见错误是只写了命令类但没实现接口,或者extra里没配class入口点。必须确保:
-
composer.json含"type": "composer-plugin"和"autoload": {"psr-4": {"MyPlugin\": "src/"}} - 主类(如
src/CleanerPlugin.php)implementsComposerPluginPluginInterface -
activate()方法中注册事件监听器,比如$composer->getEventDispatcher()->addListener('post-install-cmd', [...])
清理逻辑应放在post-install-cmd或post-update-cmd事件里
想在依赖安装/更新后自动删缓存、压缩包、dev-only文件,不能靠手动执行命令——得绑定到Composer原生命令事件。直接写CLI命令行工具不是“Composer插件”,只是外部脚本。
推荐绑定post-install-cmd(首次安装)和post-update-cmd(更新后),避免重复清理。例如:
$dispatcher->addListener('post-install-cmd', function (CommandEvent $event) {
$io = $event->getIO();
$io->write('Cleaning vendor cache...');
exec('rm -rf vendor/composer/autoload_*.php');
});
注意:exec()跨平台性差,生产环境建议用Filesystem组件(use SymfonyComponentFilesystemFilesystem;);Windows下rm -rf会失败。
composer.lock生成前不能修改vendor/内容
如果清理逻辑误删了正在构建的包(比如在pre-autoload-dump阶段清空vendor/),会导致composer install中途报错:Class XXX not found或Could not scan for classes。因为Autoload生成依赖已解压的代码。
安全边界很明确:
- ✅ 允许操作:
vendor/composer/*.json、vendor/.htaccess、临时压缩包(composer/archives/) - ❌ 禁止操作:
vendor/{package}/目录本身、vendor/autoload.php、vendor/composer/autoload_*.php(除非确认在post-*事件中) - ⚠️ 高风险:修改
vendor/会影响composer.lock哈希校验,下次install可能重装全部包
发布前必须测试global require和require --dev两种安装方式
插件行为在全局安装(composer global require my/plugin)和项目本地开发安装(composer require --dev my/plugin)下表现不同:前者影响所有项目,后者只作用于当前vendor/。很多插件作者只测了本地,结果用户全局装上后意外清掉了其他项目的缓存。
验证要点:
- 用
composer create-project --no-install新建空项目,再require --dev插件,确认post-*事件只清理该目录下的vendor - 用
composer global require安装,检查是否对~/.composer/vendor/下手——除非插件文档明确说明支持全局清理 - 插件内通过
$composer->getConfig()->get('vendor-dir')获取实际路径,别硬编码vendor/
真正难的是路径隔离和事件时机控制,不是写几行rm命令。多数失败案例都卡在这两步。











