# Plugin Standard ## 当前结论 - `app/*` 负责本地多应用与过渡代码。 - `plugin/*` 负责插件业务实现。 - 插件分发优先于本地应用分发。 - 默认本地应用为 `app/index`。 插件标准由以下部分共同约束: - `think\admin\Plugin` - `think\admin\service\AppService` - System 内置的 `plugin\system\helper\plugin\PluginMenuService` - System 内置的 `plugin\system\helper\migration\PhinxExtend` - `composer.json > extra.xadmin` - `composer.json > extra.xadmin.publish.copy` - 架构边界与安装边界测试 ## 插件包标准 ### 1. Composer 类型 - 参与运行时插件分发的组件统一使用 `think-admin-plugin`。 - 纯开发、交付辅助能力统一内置到 `ThinkPlugsSystem`,不再新增独立工具包。 - 安装协调组件 `ThinkPlugsInstall` 统一使用 `composer-plugin`,负责接管 Composer 生命周期内的自动发布与按需迁移。 ### 2. 服务发现 - 必须通过 `extra.think.services` 注册插件服务类。 - 标准服务类命名为 `plugin\\{name}\\Service`。 ### 3. 元数据 - `extra.xadmin.app` 只描述应用级元数据。 必填:`code`、`name` 可选:`prefix / prefixes / alias / space / document / description / platforms / license / icon / cover / super` - `version`、`homepage` 等标准包字段继续使用 Composer 顶层定义,不再放到 `extra.xadmin.app`。 - `extra.xadmin.menu` 按需描述菜单显示、根节点、菜单项与存在性检测。 - `extra.xadmin.migrate` 按需描述主迁移脚本信息。 - `extra.xadmin.publish.copy` 按需描述资源发布规则,统一使用 `copy` 清单。 运行时插件最小 `composer.json` 骨架: ```json { "type": "think-admin-plugin", "name": "vendor/demo-plugin", "description": "Demo Plugin for ThinkAdmin", "autoload": { "psr-4": { "plugin\\\\demo\\\\": "src" } }, "extra": { "think": { "services": [ "plugin\\\\demo\\\\Service" ] }, "xadmin": { "app": { "code": "demo", "name": "演示插件", "prefix": "demo" } } } } ``` 纯工具组件可按需保留 `type=library`,并省略 `menu / migrate / publish` 等运行时块。 ## 目录标准 ### 1. 插件根目录 - `composer.json` - `readme.md` - `readme.api.md` - `src` - `stc` - `tests` ### 2. 插件文档 - 每个插件根目录只保留两份说明文档:`readme.md` 与 `readme.api.md`。 - `readme.md` 只描述插件定位、边界、依赖与入口,不堆放接口明细、迁移细节或大段历史说明。 - `readme.api.md` 统一描述接口标准与接口列表。 - HTTP 插件在 `readme.api.md` 中按 `路由 + 请求方式 + 参数 JSONC` 组织,参数字段必须逐项写注释。 - HTTP 插件的 `readme.api.md` 必须补充标准 JSON 响应结构,至少说明 `code`、`info`、`data` 字段和常用状态码 `200/401/403/404/500`。 - 命令型或发布型组件在 `readme.api.md` 中按 `命令/配置入口 + 参数 JSONC` 组织,配置字段必须逐项写注释。 - 插件目录下不再追加第三份功能说明、临时接入文档或历史迁移说明,额外专题文档统一放到仓库 `docs/`。 ### 3. `src` 根目录 - 必须保留 `Service.php`。 - 只有确实需要全局函数时才保留 `common.php`。 - 不再新增职责模糊的根级文件。 ### 4. 常用子目录 - `controller` - `model` - `service` - `view` - `command` - `lang` - `worker` - `tests` ## 运行时标准 ### 1. 路由优先级 1. 先按插件前缀匹配。 2. 再按本地应用首段匹配。 3. 再按根目录全局路由目标声明匹配。 4. 再按动态插件切换匹配。 5. 最后回退到默认本地应用。 ### 2. 标准入口 - 本地应用页面:`/{app}/{controller}/{action}` - 插件页面:`/{plugin}/...` - 插件接口:`/api/{plugin}/{controller}/{action}` ### 3. 根路由声明 - 优先使用 `Route::bindApp()` 与 `Route::bindPlugin()`。 - 分组场景使用 `Route::appGroup()` 与 `Route::pluginGroup()`。 - 根路由里的目标地址必须写成目标应用内部的相对节点。 ### 4. 动态切换 - `_plugin` 与 `X-Plugin-App` 仅作为调试入口。 - 默认关闭,不作为正式业务路由依赖。 ### 5. JSON 响应标准 - HTTP JSON 接口统一返回 HTTP `200`,前后端不再使用 `1/0` 表示成功或失败。 - 业务状态统一写入 `code` 字段,不再重复返回 `status`。 - `200` 表示成功,业务数据通过 `data` 返回。 - `401` 表示未认证、登录过期、令牌无效或会话失效。 - `403` 表示已认证但无权限、账号禁用或访问被拒绝。 - `404` 表示接口或资源不存在。 - `500` 表示服务端异常或未分类业务异常。 ## 插件服务标准 ### 1. 基类 - 参与运行时插件发现、路由或菜单元数据注入的服务统一继承 `think\admin\Plugin`。 - 纯命令或工具组件如不参与运行时插件装配,可继续继承 `think\Service`。 ### 2. 职责 - 注册插件运行时能力。 - 处理必要的中间件或路由挂载。 - 承接 `composer.json` 中声明的插件元数据与发布规则。 - 纯工具组件只承接命令注册或工程化能力,不承担运行时插件装配职责。 ### 3. 非职责 - 不在服务类中堆放业务逻辑。 - 不在服务类中维护大量兼容桥接代码。 - 不在服务类中声明运行时元数据字段或 `menu()` 之类的旧入口。 ## 菜单与权限标准 - 菜单数据统一来自 `composer.json > extra.xadmin.menu.items`。 - 菜单引用的控制器节点必须真实存在。 - 叶子节点必须同时声明 `@auth true` 与 `@menu true`。 - 菜单写入前必须经过 `PluginMenuService::assertMenus()` 校验。 ## 数据库与发布标准 - 每个插件只保留一份最终安装迁移脚本。 - 主迁移脚本以插件内 `stc/database` 为准。 - 自动迁移开关统一来自 `composer.json > extra.xadmin.migrate`;未声明时只能提示,不能在 Composer 安装链路中强制建表。 - 发布资源统一来自 `composer.json > extra.xadmin.publish.copy`。 - 发布规则只保留 `copy`,结构化规则统一使用 `source: { to, force, exclude }` 或 `{ from, to, force, exclude }`。 - 自动发布与按需迁移统一由 `zoujingli/think-plugs-install` Composer plugin 驱动,根项目需通过 `config.allow-plugins` 显式允许。 - 首次 Composer 安装只执行发布,不自动建表;后续变更才依据 `extra.xadmin.migrate` 做自动迁移。 - 根目录 `database/migrations` 视为发布产物,不是主维护源。 - 共享表必须遵守固定归属,不允许多插件重复持有。 ## 依赖标准 - 本地插件依赖统一走 Composer `path` repository。 - 依赖图必须尽量保持无环。 - `ThinkPlugsSystem` 可以依赖 `library / static / worker`,并内置 storage 与 helper 能力。 - 业务插件不应重新把共享基础能力耦回 `system` 或 `library`。 ## 测试要求 - 新增插件必须通过安装边界、路由边界、目录边界和迁移边界测试。 - 菜单、入口、迁移和 URL 规则必须有最小回归覆盖。 ## 新插件准入清单 1. 提供独立 `composer.json`。 2. 提供 `src/Service.php`。 3. 在 `extra.xadmin.app` 中声明 `code / prefix / name`。 4. 有后台菜单时,在 `extra.xadmin.menu` 中声明菜单元数据。 5. 需要发布资源时,在 `extra.xadmin.publish.copy` 中声明规则。 6. 需要安装表结构时,在 `stc/database` 中保留唯一主迁移脚本,并通过 `extra.xadmin.migrate` 声明主脚本。 7. 运行时插件服务继承 `think\admin\Plugin`;纯工具组件按需继承 `think\Service`。 8. 不在 `Service.php` 中声明元数据字段或 `menu()` 兼容入口。 9. 补齐最小安装与路由测试。