如何制作一个遵循Composer规范的独特插件?
- 内容介绍
- 文章标签
- 相关推荐
本文共计990个文字,预计阅读时间需要4分钟。
这是最常被跳过的门板。你写的类功能再完整,只要没有+implements ComposerPluginPluginInterface+,或者漏掉了+activate(Composer $composer, IOInterface $io)+ 方法(注意参数类型不能错),Composer 就会完全忽略它。
-
activate()是唯一入口,所有事件监听、命令注册、配置读取都得放在这里;deactivate()可空实现,但不能省略 - 别在
__construct()里依赖$composer或$io—— 它们只在activate()调用时才可用 - 匿名类、无命名空间类、或命名空间与
autoload配置不匹配的类,都会导致自动加载失败,进而让PluginInterface根本无法实例化
composer.json 必须声明 "type": "composer-plugin" 并正确配置 autoload
Composer 不靠目录结构或文件名识别插件,全靠这个字段。设成 library 或留空,插件就永远不会被加载。
-
"autoload": {"psr-4": {"MyPlugin\": "src/"}}必须和你类的命名空间严格一致,比如类是MyPluginPlugin,就得放在src/Plugin.php -
"extra": {"class": "MyPlugin\Plugin"}是可选的,但建议显式指定,避免 Composer 按默认规则查找失败 -
"require": {"composer-plugin-api": "^2.0"}是必须的,不是composer/composer—— 后者是开发依赖,运行时不需要
监听事件必须在 activate() 中用 EventDispatcher 显式注册
把业务逻辑直接写在 activate() 里,只会执行一次,且无法响应后续命令。真正要起作用,得绑定到具体事件上。
- 事件名是纯字符串,如
"post-install-cmd",不是ScriptEvents::POST_INSTALL_CMD(那是脚本用的) - 监听器函数签名必须接收对应
Event子类,例如function (CommandEvent $event),类型提示缺一不可,否则会静默失效或抛ArgumentCountError - 回调里要用
use ($io, $composer)捕获上下文,闭包外无法访问它们 - 常见误判:以为
post-install-cmd在每次composer install都触发 —— 实际上它只在首次安装(无composer.lock)时触发;日常更新应监听post-update-cmd
路径、配置、composer.json 读取必须通过 $composer 实例获取
插件运行时工作目录不可靠,getcwd()、file_get_contents('composer.json')、硬编码 vendor/ 路径,全是危险操作。
- 项目根目录应通过
$composer->getConfig()->get('vendor-dir')反推,或更稳妥地用$composer->getPackage()->getAutoload()等已解析好的元数据 - 当前项目的
composer.json内容必须用$composer->getPackage()获取,它已校验 schema、normalize 过,不是原始 JSON 文件 - 用户传的配置(如
"extra": {"myplugin": {"enabled": true}})要用$composer->getPackage()->getExtra()读取,并做键存在性判断和类型校验 —— 直接访问$extra['myplugin']['enabled']可能导致Fatal Error
composer.json 也改了,但因为少了一个 implements、参数类型写错、autoload 路径对不上,就彻底失联。调试时最该先确认的,永远是插件是否真的被加载了——加一行 $io->writeError('✅ Plugin loaded'); 在 activate() 开头,比查日志快十倍。本文共计990个文字,预计阅读时间需要4分钟。
这是最常被跳过的门板。你写的类功能再完整,只要没有+implements ComposerPluginPluginInterface+,或者漏掉了+activate(Composer $composer, IOInterface $io)+ 方法(注意参数类型不能错),Composer 就会完全忽略它。
-
activate()是唯一入口,所有事件监听、命令注册、配置读取都得放在这里;deactivate()可空实现,但不能省略 - 别在
__construct()里依赖$composer或$io—— 它们只在activate()调用时才可用 - 匿名类、无命名空间类、或命名空间与
autoload配置不匹配的类,都会导致自动加载失败,进而让PluginInterface根本无法实例化
composer.json 必须声明 "type": "composer-plugin" 并正确配置 autoload
Composer 不靠目录结构或文件名识别插件,全靠这个字段。设成 library 或留空,插件就永远不会被加载。
-
"autoload": {"psr-4": {"MyPlugin\": "src/"}}必须和你类的命名空间严格一致,比如类是MyPluginPlugin,就得放在src/Plugin.php -
"extra": {"class": "MyPlugin\Plugin"}是可选的,但建议显式指定,避免 Composer 按默认规则查找失败 -
"require": {"composer-plugin-api": "^2.0"}是必须的,不是composer/composer—— 后者是开发依赖,运行时不需要
监听事件必须在 activate() 中用 EventDispatcher 显式注册
把业务逻辑直接写在 activate() 里,只会执行一次,且无法响应后续命令。真正要起作用,得绑定到具体事件上。
- 事件名是纯字符串,如
"post-install-cmd",不是ScriptEvents::POST_INSTALL_CMD(那是脚本用的) - 监听器函数签名必须接收对应
Event子类,例如function (CommandEvent $event),类型提示缺一不可,否则会静默失效或抛ArgumentCountError - 回调里要用
use ($io, $composer)捕获上下文,闭包外无法访问它们 - 常见误判:以为
post-install-cmd在每次composer install都触发 —— 实际上它只在首次安装(无composer.lock)时触发;日常更新应监听post-update-cmd
路径、配置、composer.json 读取必须通过 $composer 实例获取
插件运行时工作目录不可靠,getcwd()、file_get_contents('composer.json')、硬编码 vendor/ 路径,全是危险操作。
- 项目根目录应通过
$composer->getConfig()->get('vendor-dir')反推,或更稳妥地用$composer->getPackage()->getAutoload()等已解析好的元数据 - 当前项目的
composer.json内容必须用$composer->getPackage()获取,它已校验 schema、normalize 过,不是原始 JSON 文件 - 用户传的配置(如
"extra": {"myplugin": {"enabled": true}})要用$composer->getPackage()->getExtra()读取,并做键存在性判断和类型校验 —— 直接访问$extra['myplugin']['enabled']可能导致Fatal Error
composer.json 也改了,但因为少了一个 implements、参数类型写错、autoload 路径对不上,就彻底失联。调试时最该先确认的,永远是插件是否真的被加载了——加一行 $io->writeError('✅ Plugin loaded'); 在 activate() 开头,比查日志快十倍。
