本文由 FlintHub 开发文档归档发布。原始文档日期见标题前缀,来源:暂存20260913/FLINTHUB.md。
FlintHub — 轻量级 PHP 社区系统 完整技术文档
版本: 1.0 (SplitDB)
内核: SplitDB 纯 SQLite 分片引擎 v2.3
PHP 要求: ≥ 8.0
数据库: 零 MySQL 依赖,纯 SQLite 分片
许可证: MIT
目录
- 一、项目概述
- 二、目录结构总览
- 三、核心框架 app/Core
- 四、辅助层 app/Helpers
- 五、数据模型 app/Models
- 六、控制器与路由
- 七、模板引擎与视图系统
- 八、前端资源
- 九、SplitDB 分片存储引擎
- 十、插件系统
- 十一、多语言支持 (I18n)
- 十二、CLI 工具与脚本
- 十三、安全机制总览
- 十四、性能优化策略
- 十五、配置与部署
- 十六、项目优势与亮点总结
一、项目概述
FlintHub(燧石论坛)是一款轻量级、高性能、零 MySQL 依赖的 PHP 社区论坛系统。它基于自研的 SplitDB 纯 SQLite 分片引擎,采用季度时序分区 + 哈希分桶的多文件架构,在低资源环境下实测承载 19 万+主题、16 万+回复、5 万+用户、235 万+搜索索引行。
核心设计理念
| 理念 | 说明 |
|---|---|
| 零外部依赖 | 纯 PHP + SQLite,无需部署 MySQL/Redis/Nginx 附加模块 |
| 极致轻量 | 无 Composer 依赖,无重型前端框架,单文件入口 |
| 分片存储 | 季度 + 哈希双维度分片,单库文件极小,读写性能均衡 |
| 外置正文 | 帖子/回复正文剥离 SQLite,存为 .txt/.bin/.idx 文件 |
| 插件驱动 | 完整的钩子系统 + 独立数据库 + 多语言,插件零侵入核心 |
| 安全纵深 | CSRF、XSS、SQL 注入、频率限制、PoW 工作量证明、审计日志 |
二、目录结构总览
WWW/ ← 项目根目录
├── index.php ← 前端控制器(路由分发入口)
├── config.php ← 全局配置(数据路径、上传、邮件、Session)
├── install.php ← 安装引导页
├── version.php ← 版本号(单一版本源)
├── .htaccess ← Apache URL 重写
├── nginx-server.conf ← Nginx 配置模板
├── cron_trigger.php ← 定时任务触发器(队列消费)
│
├── app/ ← 核心应用代码
│ ├── init.php ← 应用初始化(自动加载→Session→插件→维护模式)
│ ├── Core/ ← 框架内核(6 个文件)
│ │ ├── Autoloader.php ← PSR-4 风格自动加载器
│ │ ├── Controller.php ← 控制器基类
│ │ ├── Database.php ← 数据库门面(SplitDB 统一入口)
│ │ ├── Model.php ← 基础 ORM 模型
│ │ ├── Router.php ← 路由引擎
│ │ └── TemplateCompiler.php ← 模板编译器(964 行,含图标系统)
│ ├── Helpers/ ← 辅助层(22 个文件)
│ ├── Models/ ← 数据模型层(10 个文件)
│ ├── Controllers/ ← 前台控制器(14 个)+ 后台控制器(17 个)
│ ├── Views/ ← 视图模板(PHP 模板,按功能分目录)
│ └── SplitDB/ ← 分片存储引擎(14 个文件)
│
├── assets/ ← 前端静态资源
│ ├── css/ ← 样式表(6 个主文件 + 5 个主题配色)
│ ├── js/ ← JavaScript(编辑器、认证、PoW、帖子交互)
│ ├── lib/ ← 工具库(fhajax.js、fhstate.js、qrcode.min.js)
│ ├── fonts/ ← FontAwesome 字体
│ ├── img/ ← 图片资源(emoji、图标)
│ ├── medals/ ← 勋章 SVG(10 枚)
│ ├── pwa/ ← PWA 资源(manifest、图标)
│ ├── themes/ ← 用户上传主题包
│ └── uploads/ ← 用户上传文件(头像、附件、博客封面)
│
├── plugins/ ← 插件目录(一目录一插件,28+ 个插件)
│ └── plugins_cache.json ← 插件注册缓存(含 hooks 清单)
│
├── lang/ ← 核心语言包
│ ├── zh.php ← 中文(默认)
│ ├── en.php ← 英文
│ └── zh_tw.php ← 繁体中文
│
├── data/ ← SplitDB 数据根目录(SQLite 分片文件)
│ ├── meta/ ← 元数据库(business/main_index/sessions/global_id)
│ ├── bucket/ ← 分片桶(active/ + archive/)
│ ├── extern/ ← 外置正文存储(.txt/.bin/.idx)
│ ├── runtime/ ← 运行时缓存(页面缓存、统计缓存、断点文件)
│ ├── lock/ ← 文件锁目录
│ └── log/ ← 日志目录
│
├── protected/ ← 受保护目录(Web 不可访问)
│ ├── sessions/ ← 文件 Session 备用目录
│ ├── rate_cache/ ← IP 限流缓存
│ └── error.log ← 错误日志
│
├── cli/ ← CLI 工具脚本(50+ 个)
├── docs/ ← 项目文档(审计报告、改造计划、交接文档)
└── cms插件/ ← CMS 插件(独立目录)三、核心框架 app/Core
FlintHub 的框架内核仅 6 个文件,实现了完整的 MVC 管线。
3.1 Autoloader.php — 自动加载器
职责: PSR-4 风格的类自动加载,支持 app\ 和 Plugin\ 两个命名空间。
关键设计:
app\Controllers\HomeController→app/Controllers/HomeController.phpPlugin\AiAssistant\Plugin→plugins/ai_assistant/Plugin.php(大小写容错 + 驼峰转下划线尝试)- 路径穿越防护: 禁止类名含
..,realpath校验文件必须落在 app/plugins 根目录内
3.2 Router.php — 路由引擎
职责: GET/POST/ANY 路由注册、分组、参数提取、分发。
关键设计:
- 支持
{param}参数占位符(正则提取(?P<name>[^/]+)) group('/admin', callback)支持路由分组- 二级目录支持:
BASE_PATH前缀自动剥离 - 查询参数 fallback:
?r=/forum兼容模式(禁止访问后台路径) - 安全:
route_before_dispatch钩子在路由匹配前触发,支持封禁用户拦截 - 404 处理: 渲染
errors/404视图,挂主布局
3.3 Database.php — 数据库门面
职责: SplitDB 统一门面,业务连接 + Session 连接物理隔离。
关键设计:
- 单例模式:
getInstance()获取业务连接(business.sqlite) - Session 独立连接:
getSessionConnection()连接 sessions.sqlite,避免写锁互相阻塞 - 游标自动释放: 新查询前自动关闭上一个
lastStmt游标 - SQL 计数:
getQueryCount()(业务库)+getTotalSqlCount()(全库,含分片桶/session) - 安全: PDO 异常不向浏览器泄露,真实错误只写 error.log
- 自动引导: 数据目录缺失时自动
Schema::bootstrap()建库
3.4 Model.php — 基础 ORM 模型
职责: CRUD 封装、参数化查询、安全排序、批量赋值防护。
关键设计:
$fillable白名单: 子类必须声明可更新列,update()对白名单外键拒绝并记日志(fail-closed)buildWhere安全解析器: 仅允许列名 比较运算符 :占位符AND 连接格式,拒绝 OR/IN/子查询/字面量sanitizeOrderBy: ORDER BY 只允许字母、数字、下划线、点、逗号、空格、ASC/DESC- 列名校验:
insert()过滤非法列名字符,count()防 WHERE Array 类型错误 - 标识符引用: 列名统一加双引号(SQLite 标准),防保留字冲突
3.5 Controller.php — 控制器基类
职责: 视图渲染、JSON 响应、安全重定向、权限检查。
关键设计:
view()统一渲染: 注入 currentUser/isLoggedIn/isAdmin/csrfToken/renderTime 等全局变量- 安全响应头: X-Content-Type-Options、X-Frame-Options、CSP、Permissions-Policy、HSTS
- 防开放重定向:
redirect()仅允许以/开头的相对路径,禁止//协议相对 URL - 二级目录支持: 自动拼接
BASE_PATH - 管理员二次验证:
requireAdminVerified()支持动态超时(标准 30 分钟 / 长任务 30 天) - 插件钩子:
controller_view_before在视图渲染前触发
3.6 TemplateCompiler.php — 模板编译器
职责: 自研模板引擎(964 行),支持变量输出、条件、循环、布局继承、组件 include。
关键设计:
- 模板语法:
{{$var}}(HTML 转义输出)、{!!$var!!}(原始输出)、@if/@elseif/@else/@endif、@foreach、@include、@extend/@section/@yield - 安全表达式:
safeExpr()白名单过滤条件表达式,防模板注入 - 布局继承:
extend('main')+section('content')+yield('content')机制 - 编译缓存: 模板编译为 PHP 文件缓存到
data/runtime/,修改源模板自动重新编译 - 图标系统:
$this->icon('名称')内置 400+ 图标映射(FontAwesome Unicode) - 翻译函数:
$this->t('key')直接在模板中调用多语言 - 分页组件:
$this->pagination()完整分页渲染(含省略号、首尾页) - 时间格式化:
$this->timeAgo()中文友好时间差显示
四、辅助层 app/Helpers
Helpers 层是 FlintHub 的业务能力中枢,22 个文件覆盖认证、权限、安全、搜索、缓存、邮件等全部横切关注点。
4.1 Auth.php — 用户认证
- 登录状态检查(Session
user_id) - 管理员双重校验(
role=admin+group_id=4) - 当前用户查询(请求级静态缓存,用户被删自动清 Session)
- 登录来源记录与回跳(支持 htmx
HX-Current-URL头)
4.2 Plugin.php — 插件管理器
- 插件发现: 扫描
plugins/目录,读取plugin.json元数据 - 钩子系统:
hook('name', params)触发钩子,支持多插件链式调用 + 异常隔离 - 独立数据库:
Plugin::db('插件名')返回原生 PDO 连接(插件独立 .sqlite 文件) - 权限管理:
granted('插件名', 'permission')检查插件权限(net:fetch/route:admin 等) - 原子配置写入:
writeJsonAtomic()临时文件 + rename,防并发损坏 - 激活/停用/卸载: 完整生命周期管理,调用插件自身 activate/deactivate 方法
- HTTP 请求:
Plugin::http()封装 file_get_contents 流上下文,内置超时、重定向限制
4.3 Settings.php — 站点设置
- 双层缓存: 文件缓存(
data/runtime/settings.cache)+ 请求内静态数组 - 运行时计数器:
runtimeIncr/runtimeDecr批量写入(总用户/主题/帖子/博客),请求结束时flushCounters() - 在线状态:
updateOnlineStatus()Session 写入在线记录,30 分钟超时清理 - 未读消息:
getUnreadMessageCount()请求级缓存 - 附件管理:
handleAttachments()关联附件到帖子,cleanupOrphanAttachments()清理孤儿文件
4.4 Csrf.php — CSRF 防护
- Token 30 分钟自动轮换
verify()使用hash_equals常量时间比较consume()一次性消费 Token(敏感操作后调用,防重放)rotate()仅在登录/注销时手动轮换(防并发 AJAX 403)
4.5 Permission.php — 权限系统
- 用户组: 默认 4 组(游客/普通用户/版主/管理员),支持自定义
- 版块权限: canView/canPost/canReply/canAttach 四维权限矩阵
- 权限存储:
category_permissions表,按 group_id × category_id 粒度控制 - 批量授权查询:
getAuthorizedCategoryIds()一次查出用户可访问的全部版块 ID
4.6 Points.php — 积分等级系统
- 等级配置: 11 级(新手小白 → 社区元老),可后台自定义标题/图标/颜色/所需积分
- 积分增减:
award()增加积分 + 自动升级 + 插件钩子;deduct()扣减积分 + 防透支(条件 UPDATE) - 嵌套事务感知: 调用方已在事务内时不自建事务,由外层统一提交/回滚
- 等级徽章:
renderBadge()输出带颜色的 HTML 徽章
4.7 Search.php — 搜索引擎
- 双引擎: 倒排索引优先(
search_index表),回退 LIKE 模糊搜索 - 中文分词:
Segmenter::bigram()二元切词("中华人民共和国" → ["中华","华人",...]) - 权重排序: 标题权重 3、正文权重 1,按匹配词数 × 权重求和排序
- 时间范围: 支持 24h/7d/30d/3m/6m/1y 时间过滤
- 权限感知: 搜索结果自动过滤用户无权访问的版块
- 索引重建:
SearchRebuild支持断点续建 + 指纹校验
4.8 PageCache.php — 页面静态缓存
- 访问触发式: 首页/版块列表页渲染结果缓存为静态 HTML 文件
- 永久缓存: 不按 TTL 过期,仅在发帖/回帖时
invalidate()主动失效 - 仅游客生效: 登录用户含用户态数据不缓存
- 前置缓存:
index.php入口前置,命中直接输出(约 3~10ms),完全跳过框架引导 - 多维度分键: 语言分键(zh/en)+ 用户偏好分键(列表摘要开关/长度)
4.9 RateLimiter.php — 频率限制
- 双重标识: Session 级 + IP 级(文件缓存,跨 PHP-FPM 工作进程持久化)
- 文件锁防穿透: 有限退避重试抢锁 + 锁内重读合并,防 Lost Update
- 只读判定:
isLimited()不写入记录,用于风控/验证码触发判定 - 双模式输出: API/htmx → JSON;普通页面 → 友好 HTML 429 页
- 后台可配: 限流阈值从 Settings 读取(
rate_{action}_max/window)
4.10 PoW.php — 工作量证明
- 前端自动计算
sha256(challenge + nonce)直至前 N 位为 0 - 挑战 5 分钟有效期,一次性消费(防重放)
- 难度可后台配置(1~8),默认 4
4.11 RememberMe.php — 记住登录
- 多端独立 Token: JSON 数组存储(最多 10 个),各端互不干扰
- Token 轮换: 仅轮换匹配到的那一个,其他端不受影响(防互踢)
- BEGIN IMMEDIATE: 事务起始即抢写锁,串行化同用户并发读-改-写
- 失配告警: Token 校验失败写审计日志(IP/UA 留痕)
4.12 其他 Helper
| 文件 | 职责 |
|---|---|
Content.php | HTML 净化(白标签/白属性)、CSS 样式净化、帖子摘要提取、内容编解码 |
Upload.php | 文件上传(扩展名白名单 + MIME 校验 + 缩略图生成),支持 Imagick/GD 双引擎 |
AuditLog.php | 审计日志(自动建表、IP/UA 追踪、90 天保留、过期清理) |
Mailer.php | 邮件发送(SMTP 原生 socket + PHP mail() 双模式),SMTP 密码 AES-256-CBC 加密 |
Theme.php | 主题管理(元数据解析、可用主题扫描、首页模式、夜间模式、列表摘要偏好) |
Tag.php | 标签管理(CRUD、帖子标签关联、热门标签、孤儿清理、重复合并) |
Segmenter.php | 中文分词器(bigram 二元切词 + 英文单词归一化 + 权重标注) |
SearchRebuild.php | 搜索重建断点续建(keyset 游标 + 指纹校验 + 断点文件读写) |
Captcha.php | 图片验证码(Session 哈希校验 + 盐值存储 + 3 分钟过期) |
Emoji.php | 表情包管理 |
CoverTemplate.php | 博客封面模板生成 |
五、数据模型 app/Models
Models 层继承 Model 基类,核心 4 个模型覆盖论坛的主要业务实体。
5.1 Thread.php — 主题模型(1225 行)
最复杂的模型,完全感知 SplitDB 分片架构:
- 写入流程: IDGenerator 生成全局唯一 ID → ShardRouter 路由到分片桶 → 写入 bucket 的 topic 表 → 写入 main_index.topic_index → 外置正文写入 ExternStorage → 搜索索引更新
- 读取流程: 读 main_index.topic_index 获取元数据 → bucket_path 字段定位分片桶 → 读 bucket 正文 → ExternStorage 读外置正文 → 装饰(用户名、分类名、标签、投票、摘要)
- 分片感知更新:
update()根据 bucket_path 定位正确分片桶,同步更新索引 - 软删除/恢复:
softDelete()标记 deleted_at + 更新索引状态;restore()恢复 - 批量操作:
batchDelete()按 bucket_path 分组批量删除,级联清理回复/外置文件/搜索索引/投票/标签 - 摘要提取:
attachExcerpts()从外置正文提取摘要(支持图片提取),带文件缓存 - 游标分页:
getIndexCursor()基于 keyset 分页(WHERE id > last_id),性能优于 OFFSET
5.2 Post.php — 回复模型(442 行)
- 写入: IDGenerator → ShardRouter → bucket reply 表 → reply_index → ExternStorage → 帖子回复计数更新
- 读取: reply_index 元数据 → bucket 正文 → ExternStorage → 装饰
- 桶容量守卫:
guardBucketCapacity()单桶超过 50 万行时告警
5.3 User.php — 用户模型(627 行)
- 注册/登录: 密码 bcrypt 哈希,支持邮箱验证
- 搜索: 用户名模糊搜索 + 管理员多条件筛选(角色/状态/用户组)
- 批量查询:
batchGetNames()/batchGetUsers()缓存友好型批量获取 - 级联删除:
deleteWithCascade()清理用户的所有帖子/回复/私信/附件/博客/积分/标签
5.4 Category.php — 版块模型(268 行)
- 统计缓存:
getCategoryStats()永久文件缓存 + 请求内静态缓存,发帖/回帖时主动失效 - 最新帖快照:
refreshLatestSnapshot()写入 JSON 快照文件,首页/论坛列表优先读快照 - 版块删除:
deleteWithReset()分片感知,帖子重置到其他版块(同步更新 bucket + main_index)
5.5 其他模型
| 模型 | 职责 |
|---|---|
Blog.php | 博客文章模型 |
BlogCategory.php | 博客分类模型 |
BlogComment.php | 博客评论模型 |
Message.php | 站内私信模型 |
Setting.php | 站点设置模型 |
Tag.php | 标签模型 |
六、控制器与路由
6.1 前台控制器(14 个)
| 控制器 | 路由 | 功能 |
|---|---|---|
HomeController | / | 首页(门户模式/论坛模式切换) |
ForumController | /forum, /forum/category/{id} | 论坛列表、版块帖子列表 |
ThreadController | /thread/{id} | 帖子详情、编辑、删除 |
PostController | /post/new, /post/{id}/edit | 发帖、回帖、编辑回复 |
AuthController | /login, /register, /forgot-password | 登录、注册、邮箱验证、密码重置 |
ProfileController | /profile | 个人中心(编辑资料、改密码、改头像) |
MessageController | /message/* | 站内私信(收件箱、已发送、写信) |
BlogController | /blog/* | 博客系统(列表、详情、编辑、删除) |
SearchController | /search | 全站搜索 |
TagsController | /tags, /tag/{id} | 标签列表、标签下帖子 |
ThemeController | /theme-settings | 用户主题设置(配色、布局偏好) |
ApiController | /api/* | AJAX API(投票、上传、验证码、PoW) |
AttachmentController | /attachment/{id} | 附件下载(权限跟随版块 can_view) |
6.2 后台控制器(17 个)
| 控制器 | 功能 |
|---|---|
DashboardController | 后台仪表盘(统计数据、在线用户) |
SettingsController | 站点设置(基本信息/系统/显示/邮件/搜索/限流/队列) |
UserController | 用户管理(搜索、编辑、封禁、删除) |
ThreadController | 帖子管理(搜索、编辑、置顶、精华、删除) |
CategoryController | 版块管理(增删改排序、权限设置) |
BlogController | 博客管理(分类管理、文章管理) |
TagController | 标签管理(增删改、重建) |
LevelController | 等级配置管理 |
GroupController | 用户组 + 权限管理 |
DatabaseController | SplitDB 控制台(概览/设置/引擎状态) |
PluginController | 插件管理(启用/停用/卸载/配置编辑) |
ThemeController | 主题管理(设置默认/上传/删除/自定义 CSS) |
LogController | 审计日志查看 |
VerifyController | 管理员二次验证(密码确认 + 超时控制) |
MaintenanceController | 维护模式(开关、公告文案) |
TrashedController | 回收站(已删除帖子查看/恢复/彻底删除) |
6.3 路由统计
- 前台路由:30+ 条
- 后台路由:50+ 条(含插件动态注册)
- API 路由:8 条
- 插件路由:通过
admin_route_register/route_register钩子动态注册
七、模板引擎与视图系统
7.1 模板语法
// 变量输出(HTML 转义)
{{$siteName}}
{{$currentUser.username}}
// 原始输出(不转义,慎用)
{!!$csrfToken!!}
// 条件
@if ($isLoggedIn)
欢迎, {{$currentUsername}}
@elseif ($isAdmin)
管理员
@else
游客
@endif
// 循环
@foreach ($threads as $thread)
{{$thread.title}}
@endforeach
// 布局继承
@extends('main')
@section('content')
页面标题
@endsection
// 组件 include
@include('_components/left_sidebar')
// 多语言
{{$t('forum.latest')}}
// 图标
{{$icon('home')}}7.2 视图目录结构
Views/
├── layouts/main.php ← 主布局(导航/侧边栏/页脚)
├── _components/ ← 公共组件
│ ├── left_sidebar.php ← 左侧栏(导航/用户信息)
│ ├── right_sidebar.php ← 右侧栏(热门/最新/在线)
│ └── mobile_sidebar.php ← 移动端侧边栏
├── home/index.php ← 首页
├── forum/index.php ← 论坛列表
├── forum/category.php ← 版块帖子列表
├── thread/show.php ← 帖子详情
├── thread/edit.php ← 编辑帖子
├── post/create.php ← 发帖/回帖
├── auth/login.php ← 登录
├── auth/register.php ← 注册
├── blog/ ← 博客相关视图
├── message/ ← 私信相关视图
├── search/index.php ← 搜索结果
├── profile/index.php ← 个人中心
├── tags/ ← 标签相关视图
├── admin/ ← 后台视图(20+ 个)
├── errors/404.php, 429.php ← 错误页面
└── emails/ ← 邮件模板八、前端资源
8.1 CSS 架构
| 文件 | 用途 |
|---|---|
modern.css | 主样式表(响应式布局、组件样式、暗色模式) |
style.css | 基础样式重置与通用样式 |
admin.css | 后台专用样式 |
editor.css | 帖子编辑器样式 |
portal.css | 门户首页样式 |
fontawesome.css | 图标字体样式 |
主题配色变体(CSS 变量覆盖):
modern-azure.css— 天蓝主题modern-crimson.css— 深红主题modern-jade.css— 翡翠主题modern-purple.css— 紫罗兰主题modern-night.css— 夜间模式
8.2 JavaScript
| 文件 | 用途 |
|---|---|
auth.js | 登录/注册表单交互(PoW 计算、验证码) |
editor.js | 帖子编辑器(Markdown/富文本切换、图片上传、表情插入) |
thread.js | 帖子详情页交互(投票、回复、htmx 增强) |
pow.js | PoW 工作量证明前端计算(Web Worker) |
marked.min.js | Markdown 解析器 |
turndown.js | HTML → Markdown 转换器 |
fhajax.js | 轻量 AJAX 库(封装 fetch、CSRF Token 自动注入) |
fhstate.js | 前端状态管理(Alpine.js store 集成) |
8.3 PWA 支持
manifest.webmanifest— PWA 清单文件- 图标集:192px、512px、maskable-512px、apple-touch-icon
- 支持添加到主屏幕
九、SplitDB 分片存储引擎
SplitDB 是 FlintHub 的核心存储引擎,采用季度时序分区 + 哈希分桶的多文件分片架构。
9.1 架构拓扑
请求 → ShardRouter(季度 + 哈希路由)
├── business.sqlite ← 全部非分片业务表(用户/版块/设置/标签/投票/权限/审计)
├── main_index.sqlite ← topic_index + reply_index(帖子主索引)
├── bucket/active/2026Q3/0~31.sqlite ← 分片桶(帖子/回复元数据 + 正文)
├── extern/2026/Q3/0~31/ ← 外置正文(t{id}.txt / r{id}.txt)
├── sessions.sqlite ← 独立会话库
├── global_id.sqlite ← 全局 ID 生成器
└── search_2026Q3.sqlite ← 倒排搜索索引9.2 核心组件
| 组件 | 文件 | 职责 |
|---|---|---|
| Schema | Schema.php (858 行) | 自动建库建表(幂等)、目录树创建、安全文件注入、列补丁 |
| ShardRouter | ShardRouter.php (198 行) | 季度 + 哈希路由、桶路径计算、外置正文路径、智能扩容路由 |
| DBFactory | DBFactory.php (162 行) | LRU 连接池(最多 8 个句柄)、统一 PRAGMA、WAL 校验 |
| ExternStorage | ExternStorage.php (316 行) | 外置正文原子写入(临时文件 + rename)、APCu 缓存、.bin 归档块 |
| IDGenerator | IDGenerator.php | 全局原子 ID 生成(BEGIN IMMEDIATE 锁) |
| Queue | Queue.php | 多队列任务分发(3 个队列文件,打散写入) |
| QueueConsumer | QueueConsumer.php | CAS 锁消费者(防并发消费) |
| ViewCounter | ViewCounter.php | APCu 浏览量计数(30 秒节流批量落库) |
| SearchIndexStore | SearchIndexStore.php | 季度分片倒排索引存储 |
| CountingPDO | CountingPDO.php | PDO 代理(自动统计 SQL 执行次数) |
| BucketAutoScaler | BucketAutoScaler.php | 桶自动扩容(32 → 64 → 128) |
9.3 分片策略
一级分区 — 季度时序:
- 每季度一个目录:
bucket/active/2026Q1/、bucket/active/2026Q2/ - 18 个月以上冷数据归档到
bucket/archive/
二级分区 — 哈希分桶:
- 默认 32 桶,可平滑升级 64/128
- 路由公式:
ID % 桶数量 - 读取永远以
main_index.bucket_path为准(不再二次哈希) - 零迁移扩容: 新数据路由到新增桶范围,历史数据永不迁移
外置正文存储:
- 帖子/回复正文剥离 SQLite,存为
extern/2026/Q3/0/t{id}.txt - 原子写入(临时文件 + rename)
- APCu 可选缓存(600 秒 TTL)
- .bin 归档块:小文件合并为大块,附带 .idx 索引
9.4 统一 PRAGMA 配置
PRAGMA busy_timeout = 5000; -- 写锁等待 5 秒
PRAGMA journal_mode = WAL; -- WAL 模式(并发读写)
PRAGMA synchronous = NORMAL; -- WAL 下安全且高性能
PRAGMA cache_size = -20000; -- 20MB 页缓存
PRAGMA temp_store = MEMORY; -- 临时表内存存储
PRAGMA foreign_keys = OFF; -- 跨库外键不适用,手动清理十、插件系统
10.1 插件结构
每个插件是一个独立目录,包含:
plugins/{name}/
├── plugin.json ← 元数据(名称/版本/作者/描述/钩子/权限)
├── Plugin.php ← 插件主类(activate/deactivate 方法)
├── AdminController.php ← 后台控制器(可选)
├── FrontController.php ← 前台控制器(可选)
├── hook/ ← 钩子实现
│ ├── init_after.php
│ ├── route_register.php
│ ├── admin_route_register.php
│ └── ...
├── views/ ← 插件视图
├── assets/ ← 插件静态资源(CSS/JS)
├── lang/ ← 插件语言包(zh/en/zh_tw)
├── data/ ← 插件独立数据(.sqlite)
└── cli/ ← 插件 CLI 脚本(可选)10.2 plugin.json 格式
{
"name": "AI 助手",
"version": "1.0.0",
"author": "FlintHub",
"description": "AI 自动回复新帖/新回复",
"activated": true,
"category": "community",
"icon": "robot",
"admin_url": "/admin/ai-assistant",
"hooks": {
"init_after": "hook/init_after.php",
"thread_create_after": "hook/thread_create_after.php",
"post_create_after": "hook/post_create_after.php"
},
"permissions": ["net:fetch", "route:admin"]
}10.3 可用钩子
| 钩子 | 触发时机 |
|---|---|
init_after | 应用初始化完成后 |
route_register | 前台路由注册 |
admin_route_register | 后台路由注册 |
route_before_dispatch | 路由分发前(封禁拦截) |
route_after_dispatch | 路由分发后 |
controller_view_before | 视图渲染前 |
thread_create_after | 发帖后 |
post_create_after | 回帖后 |
auth_register_after | 用户注册后 |
avatar_upload_after | 头像上传后 |
points_award_after | 积分增加后 |
points_deduct_after | 积分扣除后 |
layout_head_end | 页面 head 结束前 |
nav_plugin_links | 导航插件链接 |
nav_user_menu_items | 用户菜单项 |
right_sidebar_after | 右侧栏之后 |
10.4 已安装插件(28+ 个)
| 插件 | 分类 | 功能 |
|---|---|---|
| ai_assistant | community | AI 助手:多 AI 会员自动回复,敏感词过滤 |
| announcements | community | 公告系统:后台发布站内公告 |
| code_audit | system | 代码审计:7 维规则扫描 PHP 文件 |
| code_repo | system | 代码仓库:在线浏览 Git 仓库 |
| content_review | community | 内容审核:发帖/回帖/头像审核 + 通知 |
| daily_checkin | entertainment | 每日签到:签到获取积分,连续签到奖励 |
| dice | entertainment | 摇骰子:三颗骰子押大小游戏 |
| draft_saver | utility | 草稿保存:帖子自动保存草稿 |
| edit_info | utility | 编辑信息:显示帖子编辑记录 |
| floor_reply | community | 楼中楼:回复指定楼层 |
| forum_required_tag | community | 必填标签:发帖必须选择标签 |
| friend_links | community | 友情链接:后台管理友情链接 |
| icon_generator | utility | 图标生成:SVG 图标生成器 |
| invite | community | 邀请码:注册邀请码系统 |
| medal | community | 勋章系统:用户勋章展示与管理 |
| mod_system | community | 版主系统:版主管理工具 |
| news_aggregator | content | 今日热榜:聚合多平台热点新闻 |
| notifications | community | 通知系统:站内消息通知 |
| points_mall | commerce | 积分商城:积分兑换商品 |
| post_favorite | community | 帖子收藏:收藏/取消收藏 |
| red_packet | commerce | 红包:帖子内发积分红包 |
| required_tag | community | 必填标签(另一实现) |
| task_center | community | 任务中心:每日任务获取积分 |
| topic_vote | community | 投票帖:帖子内发起投票 |
| user_tag | community | 用户标签:用户自定义标签 |
| webhook | system | Webhook:事件回调通知 |
十一、多语言支持 (I18n)
11.1 语言探测顺序
- URL 参数
?lang=en - Cookie
flinthub_lang(30 天有效) - Session
lang - 后台设置
site_lang - 浏览器
Accept-Language头 - 中文兜底(
zh)
11.2 语言包结构
// lang/zh.php
return [
'forum.latest' => '最新帖子',
'forum.hot' => '热门帖子',
'js.vote.success' => '投票成功',
// ...
];11.3 插件语言包自动合并
插件的 lang/{lang}.php 由 I18n::load() 自动合并,无需写钩子代码。核心键优先,插件仅补充缺失键。
11.4 回退链
目标语言缺 key → 中文 → key 本身(永不白屏/报错)
十二、CLI 工具与脚本
cli/ 目录包含 50+ 个命令行脚本,覆盖数据维护、迁移、验证、冒烟测试等。
12.1 数据维护
| 脚本 | 功能 |
|---|---|
rebuild_index.php | 重建搜索索引 |
rebuild_search.php | 重建搜索(新版,支持断点续建) |
backfill_excerpts.php | 回填帖子摘要缓存 |
seed_content.php | 种子内容生成(测试数据) |
migrate.php | 数据迁移工具 |
archive.php | 冷数据归档 |
shrink_business.php | 压缩 business.sqlite |
worker.php | 队列消费者(后台常驻) |
12.2 冒烟测试(20+ 个)
| 脚本 | 测试范围 |
|---|---|
smoke_model.php | Model 基础 CRUD |
smoke_database.php | Database 连接与查询 |
smoke_thread_read.php | 帖子读取流程 |
smoke_thread_write.php | 帖子写入流程 |
smoke_post.php | 回复写入流程 |
smoke_schema.php | Schema 建表 |
smoke_install.php | 安装流程 |
smoke_frontend_flow.php | 前端页面渲染 |
smoke_id_generator.php | ID 生成器 |
smoke_queue.php | 队列系统 |
smoke_shard_router.php | 分片路由 |
smoke_extern_storage.php | 外置存储 |
smoke_viewcounter.php | 浏览量计数 |
smoke_db_factory.php | 连接池 |
smoke_business_models.php | 业务模型 |
12.3 验证脚本(20+ 个)
以 _verify_ 前缀的脚本用于验证特定功能的正确性,如 _verify_points_mall.php(积分商城)、_verify_news_aggregator.php(新闻聚合)、_verify_query_opt.php(查询优化)等。
十三、安全机制总览
FlintHub 采用纵深防御策略,从多个层面保障系统安全。
13.1 输入验证
| 层面 | 措施 |
|---|---|
| SQL 注入 | 全量参数化查询(PDO prepare/execute),Model::buildWhere 白名单解析器 |
| XSS | 模板自动 htmlspecialchars 转义,Content::sanitizeHtml 白标签/白属性净化 |
| CSRF | Token 生成 + 30 分钟轮换 + hash_equals 常量时间比较 + 一次性消费 |
| 文件上传 | 扩展名白名单 + MIME 校验(finfo)+ 文件名随机化 + 缩略图像素炸弹防护 |
| 路径穿越 | Autoloader realpath 校验、类名禁止 ..、语言码白名单清洗 |
13.2 认证与授权
| 层面 | 措施 |
|---|---|
| 密码存储 | bcrypt 哈希(password_hash) |
| 会话安全 | session.use_strict_mode=1(防 Session Fixation)、session_regenerate_id |
| 记住登录 | SHA-256 Token 哈希存储、多端独立 Token、BEGIN IMMEDIATE 串行化 |
| 管理员验证 | 二次密码确认 + 动态超时(30 分钟/30 天) |
| 权限控制 | 四维权限矩阵(canView/canPost/canReply/canAttach)× 用户组 × 版块 |
13.3 防滥用
| 层面 | 措施 |
|---|---|
| 频率限制 | Session + IP 双重标识、文件锁防穿透、后台可配阈值 |
| PoW 工作量证明 | 前端计算 SHA-256 前 N 位为 0,难度可配 |
| 验证码 | 图片验证码 + 盐值哈希 + 3 分钟过期 |
| IP 封禁 | Plugin::http 内置 IP 黑名单检查 |
13.4 安全响应头
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Referrer-Policy: strict-origin-when-cross-origin
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-eval' 'unsafe-inline'; ...
Permissions-Policy: camera=(), microphone=(), geolocation=()
Strict-Transport-Security: max-age=31536000; includeSubDomains (HTTPS 时)13.5 审计与监控
- 审计日志: 登录/注销/删除/更新/封禁/管理操作全量记录,IP/UA 追踪,90 天保留
- 错误日志: 所有异常写
protected/error.log,不向浏览器泄露 - SQL 计数: 全库 SQL 统计(business + main_index + 分片桶 + session)
十四、性能优化策略
14.1 数据库层
| 策略 | 说明 |
|---|---|
| WAL 模式 | 并发读写,写入不阻塞读取 |
| 分片文件 | 单库文件极小(每桶 32 万行上限),VACUUM 效率高 |
| 外置正文 | 正文剥离 SQLite,库文件体积极小 |
| LRU 连接池 | 最多 8 个句柄,避免重复建连 |
| keyset 分页 | WHERE id > last_id 替代 OFFSET,深分页性能恒定 |
| 游标自动释放 | 新查询前自动关闭上一个游标,防游标堆积 |
14.2 缓存层
| 策略 | 说明 |
|---|---|
| 页面静态缓存 | 游客列表页缓存为 HTML 文件,命中约 3~10ms |
| 前置缓存 | index.php 入口前置,完全跳过框架引导 |
| Settings 双层缓存 | 文件缓存 + 请求内静态数组 |
| 版块统计缓存 | 永久文件缓存,发帖/回帖时主动失效 |
| 最新帖快照 | JSON 快照文件,首页/论坛列表优先读快照 |
| APCu 缓存 | 外置正文 600 秒 TTL、浏览量 30 秒节流 |
| 运行时计数器 | 批量写入(请求结束时 flush),减少数据库写入 |
14.3 前端层
| 策略 | 说明 |
|---|---|
| htmx | 局部刷新替代整页重载 |
| Alpine.js | 轻量级响应式框架(无 Vue/React 重依赖) |
| Gzip 压缩 | 后台开关控制 |
| PWA | 支持添加到主屏幕 |
| CSS 变量 | 主题切换无需加载新样式表 |
十五、配置与部署
15.1 核心配置 config.php
// SplitDB 数据引擎
define('SPLITDB_DATA_PATH', __DIR__ . '/data');
define('SPLITDB_BUCKET_SIZE', 32); // 每季度哈希桶数量
// 上传
define('UPLOAD_PATH', __DIR__ . '/assets/uploads/');
define('MAX_FILE_SIZE', 5 * 1024 * 1024); // 5MB
define('ALLOWED_EXTENSIONS', ['jpg','jpeg','png','gif','webp','pdf','zip','doc','docx']);
// 邮件 SMTP
define('MAIL_DRIVER', 'smtp');
define('MAIL_HOST', 'smtp.qq.com');
define('MAIL_PORT', 465);
define('MAIL_ENCRYPTION', 'ssl');
// 站点
define('DEFAULT_SITE_NAME', 'FlintHub 精品论坛');
define('DEFAULT_THEME', 'modern');
define('POSTS_PER_PAGE', 20);
define('THREADS_PER_PAGE', 20);
define('BASE_PATH', ''); // 二级目录支持
define('CRON_KEY', ''); // 定时任务密钥15.2 Session 存储
- 独立 SQLite 库:
data/meta/sessions.sqlite,与业务库物理隔离 - UPSERT 写入:
ON CONFLICT(id) DO UPDATE SET data, expires - 30 分钟过期:
expires = time() + 1800 - GC 机制:
config.php每 300 秒节流清理(最多 5000 行/次)
15.3 定时任务
# cron_trigger.php 通过 HTTP 触发队列消费
*/5 * * * * curl -s "http://your-site/cron_trigger.php?key=YOUR_CRON_KEY"15.4 二级目录部署
// config.php
define('BASE_PATH', '/forum'); // 部署在 /forum 子目录Router、Controller、PageCache、I18n 等全部自动适配 BASE_PATH。
15.5 Nginx 配置
项目提供 nginx-server.conf 模板,包含:
- URL 重写规则
- 静态文件缓存
protected/和data/目录访问禁止- PHP-FPM 配置
十六、项目优势与亮点总结
16.1 技术亮点
| 亮点 | 详细说明 |
|---|---|
| 零 MySQL 依赖 | 纯 SQLite 分片,无需部署/维护数据库服务,降低运维成本至零 |
| 自研分片引擎 | 季度 + 哈希双维度分片,单库文件极小,读写性能均衡 |
| 零迁移扩容 | 新数据路由到新增桶,历史数据永不迁移,在线平滑升级 |
| 外置正文存储 | 正文剥离 SQLite,库文件体积极小,VACUUM 效率极高 |
| 极致轻量 | 无 Composer 依赖,无重型前端框架,核心代码精简 |
| 生产验证 | 实测 19 万+主题、16 万+回复、5 万+用户、235 万+搜索索引行 |
16.2 架构亮点
| 亮点 | 详细说明 |
|---|---|
| 分层清晰 | Core(框架)→ Helpers(能力)→ Models(数据)→ Controllers(业务)→ Views(展示) |
| 插件驱动 | 完整钩子系统 + 独立数据库 + 多语言,28+ 插件零侵入核心 |
| 安全纵深 | 从输入验证到输出转义,从认证到审计,多层安全防护 |
| 多语言原生 | 核心层原生 i18n 支持,插件语言包自动合并,回退链保证永不白屏 |
| 主题可定制 | CSS 变量主题系统,5 个内置配色 + 夜间模式 + 用户自定义 CSS |
16.3 运维亮点
| 亮点 | 详细说明 |
|---|---|
| 一键安装 | install.php 引导页,自动建库建表 |
| 维护模式 | 后台一键开关,管理员正常访问,游客看到精美维护页 |
| CLI 工具 | 50+ 命令行脚本,覆盖迁移、重建、测试、诊断 |
| 审计日志 | 关键操作全量记录,支持按日期/类型/用户筛选 |
| 断点续建 | 搜索索引重建支持中断恢复,指纹校验防设置变更 |
16.4 开发体验亮点
| 亮点 | 详细说明 |
|---|---|
| 无框架锁定 | 纯 PHP 原生实现,无 Laravel/Symfony 依赖,学习曲线极低 |
| 模板语法简洁 | @if/@foreach/@include 类 Blade 语法,编译为 PHP 缓存 |
| 冒烟测试 | 20+ 冒烟测试脚本,覆盖核心链路,CLI 一键验证 |
| 文档完善 | 审计报告、改造计划、交接文档、白皮书齐全 |
| 二级目录支持 | 全链路 BASE_PATH 适配,可部署在任意子目录 |
FlintHub — 用最少的资源,承载最大的社区。
A lightweight PHP community system powered by SplitDB, the sharded SQLite storage engine.