🔌 插件注册
ThinkAdmin 提供完善的插件注册服务机制,基于 ThinkPHP 的服务层,使每个插件能够像独立的子应用一样运作。
🚀 主要功能
- 独立运行: 每个插件像独立的子应用一样运作
- 服务层集成: 基于 ThinkPHP 服务层机制
- 自动初始化: 通过 Service 类完成全局初始化
- 配置管理: 支持 composer.json 配置文件
- 依赖管理: 自动管理插件依赖关系
- 灵活扩展: 提供灵活的插件扩展机制
📋 插件类型
1. 本地插件
- 存储方式: 直接放置在本地目录
- 配置文件: 根目录需要包含
composer.json文件 - 版本要求: 必需指定版本号为
dev-master或其他开发分支 - 自动加载: 需要配置
autoload自动加载规则
2. 开放插件
- 发布平台: 发布到 Composer 管理平台
- 安装方式: 通过
composer require vendor/package安装 - 版本管理: 支持版本控制和更新管理
- 依赖解析: 自动解析和安装依赖
3. 私有插件
- 专属平台: 上传到 ThinkAdmin 专属平台
- Token 认证: 通过插件中心登录生成 token
- 安装方式: 与开放插件相同的安装方式
- 状态: 目前未上线
⚙️ 配置要求
必需文件
- composer.json: 插件元数据和依赖配置
- Service 类: 插件服务注册类
- 自动加载: 配置 autoload 自动加载规则
初始化机制
- 普通模块: 使用
sys.php进行全局初始化 - 插件模块: 依赖 Service 类完成全局初始化
- 服务注册: 通过 Service 类注册插件服务
插件的三种类型
- 本地插件,插件直接放置在本地某个目录,其根目录需要包含 composer.json 文件;
- 开放插件,将插件发布到 Composer 管理平台,通过
composer require vendor/package安装; - 私有插件,将插件上传到 ThinkAdmin 专属平台,通过插件中心登录生成 token,同上面的安装方式 ( 未上线 );
1. 本地插件特性
本地插件是基于 Composer 的 repositories.type 为 path 实现,参数 url 指向到插件根目录。
项目根 composer.json 配置 repositories 对象并设置插件所在位置,本地插件必需指定版本号为 dev-master 或其他开发分支。
注意事项:
- 需要在插件的
composer.json配置autoload自动加载规则,否则无法实现自动加载Class类; - 本地插件不建议使用
ThinkAdmin插件的自毁机制 (clear),有可能造成原插件目录被意外删除;
以下项目根 composer.json 的配置案例中 zoujingli/think-plugs-admin 为插件包名,需要替换为你自己的包名。
{
"type": "project",
"require": {
"zoujingli/think-plugs-admin": "dev-master"
},
"repositories": {
"ThinkAdminPlugs": {
"type": "path",
"url": "../think-plugs-admin"
}
},
"autoload": {
"psr-0": {
"": "extend"
},
"psr-4": {
"app\\": "app"
}
}
}2. 开放插件特性:
将应用插件发布到 Composer 平台,使用 composer require plugs-package-name 安装。
3. 私有插件特性:
私有插件与线上插件一致,区别在于发布的平台不同,后期会针对此类型详细描述!
插件的配置参数
应用插件 composer.json 具体配置参数如下:
- 插件类型 ( 固定的 ):think-admin-plugin
- 插件名称 ( 自定义 ):zouingli/think-plugs-admin
- 插件信息 ( 自定义 ):可选,配置插件基本信息,展示在插件说明
- 安装配置 ( 自定义 ):可选,支持安装的规则请阅读《插件安装规则》
- 插件服务 ( 自定义 ):需要继承
think\admin\Plugin并在composer.json里面注册; - 如果是本地插件且未发布到线上,需要增加
version:"dev-master"配置;
{
"type": "think-admin-plugin",
"name": "zoujingli/think-plugs-admin",
"license": "MIT",
"homepage": "https://thinkadmin.top",
"description": "Admin Plugin for ThinkAdmin",
"authors": [
{
"name": "Anyon",
"email": "zoujingli@qq.com"
}
],
"require": {
"php": ">7.1",
"ext-json": "*",
"topthink/framework": "^6.0|^8.0",
"zoujingli/think-library": "^6.1|@dev"
},
"autoload": {
"psr-4": {
"app\\admin\\": "src"
}
},
"extra": {
"think": {
"services": [
"app\\admin\\Service"
]
},
"config": {
"type": "module",
"name": "系统后台管理",
"cover": "可选,插件的封面图片,仅支持 https 协议的图片链接",
"document": "https://thinkadmin.top/plugin/think-plugs-admin.html",
"platforms": "可选,插件支持的平台,如:['wxapp','wxweb','h5wap','h5web']",
"description": "后台基础管理模块,系统账号及安全配置管理。",
"license": "可选,插件授权协议,如:['MIT', 'VIP']"
},
"plugin": {
"copy": {
"src": "!app/admin",
"stc/database": "database/migrations"
},
"clear": true
}
}
}配置说明:
- type: 固定为
think-admin-plugin - name: 插件包名,格式为
vendor/package-name - autoload: PSR-4 自动加载规则,定义插件的命名空间映射
- extra.think.services: 插件服务注册类,必须指向继承
Plugin的 Service 类 - extra.config: 插件基本信息配置
type: 插件类型,module表示模块插件,plugin表示普通插件name: 插件中文名称document: 插件文档链接description: 插件描述license: 授权协议(数组格式)
- extra.plugin: 插件安装配置
copy: 文件复制规则,!开头表示绝对复制(先删除再复制)clear: 是否在安装后清理原安装目录
插件服务注册类
插件的服务类需要继承 think\admin\Plugin 类,必须实现静态方法 menu() 来定义插件菜单。
基础属性
在插件的服务类中,可以配置以下属性:
| 属性 | 类型 | 必填 | 说明 |
|---|---|---|---|
$package | string | 是 | 插件包名(如:zoujingli/think-plugs-admin) |
$appCode | string | 否 | 插件编码(自动从命名空间计算,如:admin、plugin-account) |
$appName | string | 是 | 插件名称(如:系统管理) |
$appPath | string | 否 | 插件路径(自动计算) |
$appAlias | string | 否 | 插件别名(用于路由映射) |
$appSpace | string | 否 | 插件命名空间(自动从类命名空间计算) |
$appService | string | 否 | 服务注册类(默认为当前类) |
基础示例
<?php
declare(strict_types=1);
namespace app\admin;
use think\admin\Plugin;
/**
* 插件服务注册
* @class Service
* @package app\admin
*/
class Service extends Plugin
{
/**
* 定义插件名称
* @var string
*/
protected $appName = '系统管理';
/**
* 定义安装包名
* @var string
*/
protected $package = 'zoujingli/think-plugs-admin';
/**
* 定义插件中心菜单
* @return array
*/
public static function menu(): array
{
return [
[
'name' => '系统配置',
'subs' => [
['name' => '系统参数配置', 'icon' => 'layui-icon layui-icon-set', 'node' => 'admin/config/index'],
['name' => '系统任务管理', 'icon' => 'layui-icon layui-icon-log', 'node' => 'admin/queue/index'],
['name' => '系统日志管理', 'icon' => 'layui-icon layui-icon-form', 'node' => 'admin/oplog/index'],
['name' => '数据字典管理', 'icon' => 'layui-icon layui-icon-code-circle', 'node' => 'admin/base/index'],
['name' => '系统文件管理', 'icon' => 'layui-icon layui-icon-carousel', 'node' => 'admin/file/index'],
['name' => '系统菜单管理', 'icon' => 'layui-icon layui-icon-layouts', 'node' => 'admin/menu/index'],
],
],
[
'name' => '权限管理',
'subs' => [
['name' => '系统权限管理', 'icon' => 'layui-icon layui-icon-vercode', 'node' => 'admin/auth/index'],
['name' => '系统用户管理', 'icon' => 'layui-icon layui-icon-username', 'node' => 'admin/user/index'],
],
],
];
}
}高级示例(带服务注册)
<?php
declare(strict_types=1);
namespace app\wechat;
use app\wechat\command\Auto;
use app\wechat\command\Fans;
use app\wechat\service\AutoService;
use think\admin\Plugin;
use think\Request;
/**
* 组件注册服务
* @class Service
* @package app\wechat
*/
class Service extends Plugin
{
/**
* 定义插件名称
* @var string
*/
protected $appName = '微信管理';
/**
* 定义安装包名
* @var string
*/
protected $package = 'zoujingli/think-plugs-wechat';
/**
* 注册组件服务
* @return void
*/
public function register(): void
{
// 注册模块指令
$this->commands([Fans::class, Auto::class]);
// 注册事件监听
$this->app->event->listen('WechatFansSubscribe', static function ($openid) {
AutoService::register($openid);
});
// 注册路由
$this->app->route->any('/plugin-wxpay-notify/:vars', static function (Request $request) {
// 处理支付通知
return PaymentService::notify($data);
});
}
/**
* 定义插件菜单
* @return array
*/
public static function menu(): array
{
$code = app(static::class)->appCode;
return [
[
'name' => '微信管理',
'subs' => [
['name' => '微信接口配置', 'icon' => 'layui-icon layui-icon-set', 'node' => "{$code}/config/options"],
['name' => '微信支付配置', 'icon' => 'layui-icon layui-icon-rmb', 'node' => "{$code}/config/payment"],
],
],
[
'name' => '微信定制',
'subs' => [
['name' => '微信粉丝管理', 'icon' => 'layui-icon layui-icon-username', 'node' => "{$code}/fans/index"],
['name' => '微信图文管理', 'icon' => 'layui-icon layui-icon-template-1', 'node' => "{$code}/news/index"],
['name' => '微信菜单配置', 'icon' => 'layui-icon layui-icon-cellphone', 'node' => "{$code}/menu/index"],
],
],
];
}
}使用 appCode 动态获取插件编码
在菜单定义中,可以使用 app(static::class)->appCode 来动态获取插件编码:
public static function menu(): array
{
$code = app(static::class)->appCode; // 获取插件编码,如:plugin-account
return [
[
'name' => '用户管理',
'subs' => [
['name' => '用户账号管理', 'node' => "{$code}/master/index"],
['name' => '终端账号管理', 'node' => "{$code}/device/index"],
],
],
];
}合并其他插件菜单
插件可以合并其他插件的菜单,例如支付插件合并账号插件的菜单:
<?php
namespace plugin\payment;
use plugin\account\Service as AccountService;
use think\admin\Plugin;
class Service extends Plugin
{
protected $appName = '支付管理';
protected $package = 'zoujingli/think-plugs-payment';
public static function menu(): array
{
$code = app(static::class)->appCode;
// 合并账号插件的菜单
return array_merge(AccountService::menu(), [
[
'name' => '支付管理',
'subs' => [
['name' => '支付配置管理', 'node' => "{$code}/config/index"],
['name' => '支付行为管理', 'node' => "{$code}/record/index"],
],
]
]);
}
}