Xiuno BBS 开发实践教程 - 改造现有系统之增加列实现自己所需功能
# Xiuno BBS 开发实践教程 - 改造现有系统之增加列实现自己所需功能
## 零、前置知识要求
请先阅读并理解《Xiuno BBS 开发实践教程 - 网站大事记》,因为你将直接操作数据库表结构,并使用 `db_` 系列函数。
同时需掌握基本的 PHP、HTML、MySQL 以及 Xiuno BBS 的 hook 机制。
## 一、需求
我们希望在每个帖子详情页中显示:**该帖子是由用户通过什么设备发布的**(如网页端、iOS、Android、微信小程序等)。
这不仅能增强社区的互动感,还能为后续的数据分析(如用户终端分布)提供基础。
## 二、为什么选择直接修改 thread 表?
你可能会问:为什么不新建一张表(如 `bbs_thread_client`)来存储设备信息?
答案是:**简单、高效、符合 ORM 设计**。
Xiuno BBS 的“ORM”(即 `db_` 系列函数)在读取 `thread` 表时,会自动返回所有字段的关联数组。
只要我们在 `bbs_thread` 表中新增一列,`thread_read()`、`thread_find()` 等函数就会**自动包含该字段**,无需额外 JOIN 查询(且Xiuno BBS也提供的数据库函数没有join功能),也无需修改核心 Model 逻辑。并且还能利用缓存机制更高效(因为 `thread` 本身已被缓存,使用`thread_read_cache`即可获得缓存里的帖子信息),而且当删除帖子的时候,新增列的数据也会随着消失,数据一致性高(与帖子生命周期一致)。
## 三、数据库变更:新增 `client_type` 字段
### 1. SQL 语句设计
```sql
ALTER TABLE bbs_thread ADD COLUMN client_type VARCHAR(50) DEFAULT '' COMMENT '用户发帖设备类型';
```
注意:表前缀 `{tablepre}` 不一定是 `bbs_`,需动态获取。请继续看下去。
### 2. 插件安装文件 `install.php`
```php
tablepre;// 表前缀
$sql = "ALTER TABLE {$tablepre}thread ADD COLUMN client_type VARCHAR(50) DEFAULT '' COMMENT '用户发帖设备类型'"; // 准备SQL
db_exec($sql); // 执行
```
### 3. 插件卸载文件 `unstall.php`
是的,文件名确实是 `unstall.php`,这是 Xiuno BBS 的约定。
```php
tablepre;// 表前缀
$sql = "ALTER TABLE {$tablepre}thread DROP COLUMN client_type"; // 准备SQL
db_exec($sql); // 执行
```
提示:生产环境中建议先检查列是否存在,避免重复执行报错。但在教学插件中可简化处理。
## 四、业务逻辑:在发帖时自动识别设备类型
我们利用**hook 机制**,在帖子创建前插入设备识别逻辑。
Hook 文件:`hook/thread_create_thread_before.php`
```php
// 获取用户代理字符串
$ua = $_SERVER['HTTP_USER_AGENT'] ?? '';
$client_type = 'web'; // 默认为网页端
$client_type = 'unknown';
if (strpos($ua, 'android') !== false) {
$client_type = 'android';
} elseif (strpos($ua, 'iphone') !== false || strpos($ua, 'ipad') !== false) {
$client_type = 'ios';
} elseif (strpos($ua, 'windows phone') !== false) {
$client_type = 'windows_phone'; // RIP 微软移动端战略
} elseif (strpos($ua, 'micromessenger') !== false) {
if (strpos($ua, 'miniprogram') !== false) {
$client_type = 'mini-program';
} else {
$client_type = 'wechat'; // 微信内置浏览器
}
} elseif (strpos($ua, 'mobile') !== false) {
$client_type = 'mobile';
} elseif (strpos($ua, 'windows') !== false || strpos($ua, 'macintosh') !== false || strpos($ua, 'linux') !== false) {
$client_type = 'web';
}
// 注入到即将插入数据库的 $thread 数组中
$thread['client_type'] = $client_type;
```
其中,`$thread`是即将写入数据库的数组,我们直接追加字段即可。
## 五、前端展示:在帖子详情页显示设备类型
Hook 文件:`hook/thread_views_after.htm`
```php
· 来自
'网页端',
'ios' => 'iPhone客户端',
'android' => '安卓客户端',
'windows_phone' => 'Windows Phone',
'mini-program' => '微信小程序',
'wechat' => '微信浏览器',
'mobile' => '移动端',
'unknown' => '未知设备'
];
// 安全兜底:防止未定义键
$display_type = isset($client_type_map[$thread['client_type']]) ? $client_type_map[$thread['client_type']] : $client_type_map['unknown'];
?>
```
## 六、插件目录结构
- my_thread_clienttype/
- conf.json
- install.php
- unstall.php
- hook/
- thread_create_thread_before.php
- thread_views_after.htm
conf.json内容:
```json
{
"name": "帖子设备标识",
"brief": "教学用插件。在帖子中显示用户发帖所用设备类型",
"version": "1.0.0",
"bbs_version": "4.0.4",
"installed": 0,
"enable": 0,
"hooks_rank": [],
"overwrites_rank": [],
"dependencies": []
}
```
## 结语
通过本教程,你学会了:
- 如何安全地修改 Xiuno BBS 核心表结构
- 如何利用 hook 机制无侵入式扩展业务逻辑
- 如何让新增字段自动融入现有 ORM 体系
这正是 Xiuno BBS 插件开发的精髓:**小改动,大效果;低耦合,高复用**。