03-插件目录结构与规范
# 第3章 插件目录结构与规范
## 3.1 插件ID命名规范
格式: `作者标识_功能名称_自由描述`(最多三段,用下划线分隔)
| 示例 | 解读 |
|------|------|
| `xn_search` | xn(修罗官方) + search(搜索) |
| `xn_tag` | xn(修罗官方) + tag(标签) |
| `tt_sign` | tt(作者标识) + sign(签到) |
| `tt_credits` | tt(作者标识) + credits(积分) |
| `haya_favorite` | haya(作者标识) + favorite(收藏) |
| `abs_theme_aether` | abs(作者标识) + theme(主题类) + aether(主题名) |
**重要规则**:
- 功能名称相同的主题类插件互斥(同一时间只能启用一个主题)
- 目录名即插件ID,全局唯一
- 只允许小写字母、数字、下划线
- 主题类插件必须包含`theme`关键词
## 3.2 标准目录结构
### 3.2.1 最简插件(仅Hook注入)
```
my_plugin/
├── conf.json # 必须 - 插件配置
├── icon.png # 推荐 - 插件图标(64x64)
└── hook/ # 必须 - Hook文件目录
├── index_js.htm # 在首页JS区域注入代码
└── my_end.php # 在个人中心路由末尾注入逻辑
```
### 3.2.2 标准插件(含路由和视图)
```
my_plugin/
├── conf.json # 插件配置
├── icon.png # 插件图标
├── install.php # 安装脚本
├── unstall.php # 卸载脚本
├── upgrade.php # 升级脚本(可选)
├── setting.php # 设置页面逻辑
├── setting.htm # 设置页面模板
├── hook/ # Hook文件目录
│ ├── index_route_case_end.php # 注册路由
│ ├── model_inc_file.php # 注入Model文件
│ ├── my_end.php # 个人中心路由
│ ├── index_site_brief_after.htm # 首页注入UI
│ └── thread_js.htm # 帖子页注入JS
├── route/ # 路由文件目录
│ └── mypage.php # 自定义路由处理
├── model/ # Model文件目录
│ └── my_model.func.php # 自定义数据模型
└── view/ # 视图文件目录
└── htm/
└── mypage.htm # 自定义页面模板
```
### 3.2.3 复杂插件(含后台管理、静态资源)
```
my_plugin/
├── conf.json
├── icon.png
├── install.php
├── unstall.php
├── upgrade.php
├── setting.php
├── setting.htm
├── admin_mymodule.php # 后台管理路由
├── hook/
│ ├── index_route_case_end.php
│ ├── admin_index_route_case_end.php # 后台路由注册
│ ├── model_inc_file.php
│ ├── model_xxx_end.php # Model层hook
│ └── ...
├── route/
│ └── mypage.php
├── model/
│ └── my_model.func.php
├── view/
│ └── htm/
│ ├── mypage.htm
│ └── admin_mymodule.htm # 后台管理页面
└── static/ # 静态资源目录
├── img/ # 图片
├── css/ # 样式
├── js/ # 脚本
└── index.htm # 防目录浏览
```
### 3.2.4 主题类插件
```
my_theme_xxx/
├── conf.json
├── icon.png
├── hook/ # 轻量修改:通过hook注入CSS/JS
│ └── header_bootstrap_bbs_after.htm
├── overwrite/ # 深度修改:覆盖核心模板
│ └── view/
│ └── htm/
│ ├── header.inc.htm
│ ├── footer.inc.htm
│ ├── index.htm
│ └── thread.htm
└── view/
└── css/
└── custom.css
```
## 3.3 conf.json 详解
### 3.3.1 完整字段说明
```json
{
"name": "插件中文名",
"brief": "插件简介,一句话描述功能",
"version": "1.0.0",
"bbs_version": "4.0",
"installed": 0,
"enable": 0,
"hooks_rank": {
"hook_name.htm": 0,
"hook_name.php": 0
},
"overwrites_rank": {
"view/htm/header.inc.htm": 0
},
"dependencies": {
"tt_credits": "1.09"
}
}
```
### 3.3.2 字段详解
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `name` | string | 是 | 插件显示名称 |
| `brief` | string | 是 | 插件简介 |
| `version` | string | 是 | 插件版本号,建议语义化版本 |
| `bbs_version` | string | 是 | 兼容的BBS最低版本 |
| `installed` | int | 是 | 安装状态,0=未安装,1=已安装(系统自动维护) |
| `enable` | int | 是 | 启用状态,0=未启用,1=已启用(系统自动维护) |
| `hooks_rank` | object | 否 | Hook权重映射,key=hook名,value=权重值(越大越后执行) |
| `overwrites_rank` | object | 否 | Overwrite权重映射,key=相对文件路径,value=权重值 |
| `dependencies` | object/array | 否 | 依赖插件,key=插件目录名,value=最低版本号 |
### 3.3.3 hooks_rank 使用场景
**场景1: 多插件竞争同一hook点,需要控制执行顺序**
```json
{
"hooks_rank": {
"thread_plugin_body.htm": 500
}
}
```
权重500的插件会在权重0的插件之后执行(内容排在后面)。
**场景2: 需要优先执行(如积分插件需要在其他插件之前扣除积分)**
```json
{
"hooks_rank": {
"post_post_end.php": -10
}
}
```
负值权重使插件优先执行。
**场景3: VIP插件需要在用户名前后分别执行**
```json
{
"hooks_rank": {
"thread_username_before.htm": -100,
"thread_username_after.htm": 100
}
}
```
`_before`用负值先执行(保存原始用户名),`_after`用正值后执行(添加VIP标记)。
## 3.4 文件编码规范
- 所有PHP文件: UTF-8 无BOM
- 所有JSON文件: UTF-8 无BOM
- 所有HTM文件: UTF-8 无BOM
- 换行符: LF (Unix风格)
> **坑**: Windows编辑器可能默认保存为UTF-8 with BOM,会导致`xn_json_decode()`解析失败。Xiuno的`xn_json_decode()`会自动去除BOM头,但最好从源头避免。
## 3.5 PHP保护头规范
所有PHP类型的hook文件必须以`