开源社区论坛系统完整开发指南
yuanbbs/ ├── admin/ # 后台控制器 ├── core/ # 核心类库 │ ├── Database.php # 数据库操作类 │ ├── YuanTemplate.php # 模板引擎 │ └── Plugin.php # 插件系统 ├── forum/ # 前台论坛控制器 ├── include/ # 公共文件 │ ├── init.php # 初始化文件 │ └── functions.php # 公共函数库 ├── member/ # 用户中心控制器 ├── plugin/ # 插件目录 ├── template/ # 主题模板目录 ├── static/ # 静态资源 ├── cache/ # 缓存目录 ├── config.php # 配置文件 ├── index.php # 首页入口 ├── admin.php # 后台入口 ├── forum.php # 论坛入口 └── member.php # 用户中心入口
请求流程:
用户请求 → 入口文件(index.php/admin.php/forum.php/member.php)
→ 路由解析(?c=controller&a=action)
→ 控制器
→ 模型/数据库操作
→ 模板渲染
→ 输出响应
控制器命名规则:
- 文件名:XxxController.php(大驼峰)
- 类名:XxxController
- 方法名:小驼峰,如 index(), list(), edit()
示例URL:
- index.php?c=forum&a=index → ForumController::index()
- admin.php?c=user&a=edit → UserController::edit()
<?php
class ExampleController {
public function index() {
global $db, $template;
$data = $db->select('table', '*', 'status = 1', array(), 'id DESC');
$template->assign('title', '页面标题');
$template->assign('data', $data);
$template->display('example/index.html');
}
public function edit() {
global $db, $template;
$id = isset($_GET['id']) ? intval($_GET['id']) : 0;
if ($_POST) {
$this->doEdit($id);
return;
}
$item = $db->getOne('table', '*', 'id = ?', array($id));
$template->assign('title', '编辑');
$template->assign('item', $item);
$template->display('example/edit.html');
}
private function doEdit($id) {
global $db;
checkCsrf();
$name = trim($_POST['name']);
if (empty($name)) {
showMessage('名称不能为空', 'index.php?c=example&a=edit&id=' . $id);
}
$data = array(
'name' => $name,
'updated_at' => time()
);
if ($db->update('table', $data, 'id = ?', array($id))) {
showMessage('更新成功', 'index.php?c=example');
}
}
}
?>
// 获取全局变量
global $db; // 数据库实例
global $template; // 模板引擎实例
global $config; // 系统配置
// 检查用户登录
checkLogin(); // 未登录跳转到登录页
// 检查管理员权限
checkAdmin(); // 非管理员拒绝访问
// CSRF防护(POST请求必须)
checkCsrf(); // 验证CSRF Token
// 显示消息并跳转
showMessage('操作成功', 'index.php');
// 获取当前用户信息
$user = $_SESSION['user'];
$uid = $_SESSION['user']['uid'];
// 分页处理
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
$perpage = 20;
$pagination = pagination($total, $page, $perpage, 'index.php?c=example');
// 查询单条记录
$user = $db->getOne('users', '*', 'uid = ?', array(1));
// 查询多条记录
$users = $db->select('users', 'uid, username, email', 'status = 1', array(), 'uid DESC', '0, 10');
// 统计记录数
$count = $db->count('users', 'status = 1', array());
// 插入记录
$insertId = $db->insert('users', array(
'username' => 'test',
'email' => 'test@example.com',
'password' => passwordHash('123456'),
'reg_time' => time()
));
// 更新记录
$affected = $db->update('users', array(
'username' => 'newname',
'updated_at' => time()
), 'uid = ?', array(1));
// 删除记录
$affected = $db->delete('users', 'uid = ?', array(1));
// 执行原生SQL
$results = $db->query('SELECT * FROM users WHERE uid > ?', array(0));
users - 用户表 ├── uid - 用户ID(主键) ├── username - 用户名 ├── email - 邮箱 ├── password - 密码(bcrypt加密) ├── group_id - 用户组ID ├── status - 状态(0禁用, 1正常, 2待激活) ├── reg_time - 注册时间 └── last_login - 最后登录时间 threads - 主题表 ├── tid - 主题ID ├── fid - 版块ID ├── uid - 作者ID ├── title - 标题 ├── content - 内容 ├── views - 浏览数 ├── replies - 回复数 └── status - 状态 posts - 回复表 ├── pid - 回复ID ├── tid - 主题ID ├── uid - 作者ID ├── content - 内容 └── created_at - 创建时间 forums - 版块表 ├── fid - 版块ID ├── name - 版块名称 ├── description - 描述 ├── parent_id - 父版块ID └── status - 状态
【变量输出】
- 输出变量
- 输出对象属性/数组键
- 输出数组元素
开发文档 - 带默认值的输出
【条件判断】
请先登录
【循环遍历】
【包含模板】
开发文档 - 苗Matrix
【调用函数】
【调用钩子】
4.2 控制器中操作模板
// 赋值变量到模板
$template->assign('title', '页面标题');
$template->assign('user', $userData);
// 显示模板
$template->display('forum/index.html');
五、插件开发
5.1 插件目录结构
plugin/hello_world/
├── plugin.info.php # 插件信息(必需)
├── hooks.php # 钩子实现(必需)
├── config.php # 插件配置页面(可选)
├── install.php # 安装脚本(可选)
├── install.sql # 安装SQL(可选)
└── controllers/ # 自定义控制器(可选)
5.2 plugin.info.php 配置
<?php
return array(
'name' => 'Hello World',
'description' => '示例插件',
'version' => '1.0.0',
'author' => '苗Matrix',
'enabled' => true,
'hooks' => array('header_end', 'footer_start'),
'config' => array(
array(
'name' => 'show_text',
'title' => '显示文本',
'type' => 'text',
'default' => 'Hello!'
)
)
);
?>
5.3 hooks.php 钩子实现
<?php
if (!function_exists('hook_header_end')) {
function hook_header_end($params = array()) {
$config = Plugin::getConfig('hello_world');
echo '<style>.hello-world{color:#667eea;}</style>';
}
}
?>
5.4 插件API
// 获取插件配置
$config = Plugin::getConfig('hello_world');
// 更新插件配置
Plugin::updateConfig('hello_world', array('show_text' => 'New Text'));
// 检查插件是否启用
if (Plugin::isEnabled('hello_world')) {
// 插件已启用
}
六、主题开发
6.1 主题目录结构
template/my_theme/
├── theme.info.php # 主题信息(必需)
├── screenshot.png # 主题截图(可选)
├── css/
│ └── style.css
├── js/
│ └── main.js
├── images/
├── common/
│ ├── header.html
│ └── footer.html
├── forum/
│ ├── index.html
│ └── thread.html
└── member/
├── login.html
└── profile.html
6.2 theme.info.php 配置
<?php
return array(
'title' => '我的主题',
'description' => '一个现代化的论坛主题',
'version' => '1.0.0',
'author' => '苗Matrix',
'thumbnail' => 'screenshot.png',
'parent' => 'default', // 父主题(可选)
'settings' => array(
array(
'name' => 'primary_color',
'title' => '主色调',
'type' => 'color',
'default' => '#667eea'
)
)
);
?>
七、钩子系统
7.1 可用钩子列表
钩子名称
位置说明
参数
header_end
页头结束位置
无
footer_start
页脚开始位置
无
login_form_bottom
登录表单底部
无
register_form_bottom
注册表单底部
无
admin_index
后台首页
无
thread_view_before
帖子内容前
thread: 帖子信息
thread_view_after
帖子内容后
thread: 帖子信息
user_login_after
用户登录后
user: 用户信息
thread_create_after
发帖后
tid: 主题ID
7.2 触发钩子
// 在控制器中触发钩子
hook_trigger('thread_create_after', array(
'tid' => $tid,
'uid' => $uid
));
// 在模板中放置钩子位置
八、公共函数库
8.1 安全函数
// CSRF防护
checkCsrf(); // 验证POST中的CSRF Token
checkCsrfGet(); // 验证GET中的CSRF Token
csrfToken(); // 获取当前CSRF Token
csrfField(); // 输出CSRF隐藏字段HTML
// 密码处理
passwordHash($password); // 密码加密(bcrypt)
passwordVerify($password, $hash); // 验证密码
// 输入验证
validateEmail($email); // 验证邮箱格式
validateUrl($url); // 验证URL格式
// 数据脱敏
maskEmail($email); // 邮箱脱敏:t***@example.com
maskPhone($phone); // 手机脱敏:138****8888
8.2 工具函数
// 时间处理
formatTime($time, 'Y-m-d H:i:s'); // 格式化时间戳
getRelativeTime($timestamp); // 相对时间:刚刚、5分钟前
// 字符串处理
randomStr($length); // 生成随机字符串
// 分页
pagination($total, $page, $perpage, $url); // 生成分页HTML
// 消息提示
showMessage($message, $url); // 显示消息并跳转
// 权限检查
checkLogin(); // 检查登录
checkAdmin(); // 检查管理员权限
// 邮件发送
sendMail($to, $subject, $content); // 发送邮件
九、安全规范
9.1 SQL注入防护
// ✅ 正确:使用参数化查询
$user = $db->getOne('users', '*', 'uid = ?', array($uid));
// ❌ 错误:直接拼接SQL
$user = $db->query("SELECT * FROM users WHERE uid = $uid");
9.2 XSS防护
// ✅ 正确:输出时转义
echo htmlspecialchars($userInput, ENT_QUOTES, 'UTF-8');
// ❌ 错误:直接输出
echo $userInput;
9.3 CSRF防护
// 表单中必须包含CSRF Token
<form method="post">
...
</form>
// 控制器中验证
public function save() {
checkCsrf(); // 必须调用
// ...
}
9.4 权限控制
// 后台控制器必须检查管理员权限
class AdminController {
public function index() {
checkAdmin(); // 非管理员拒绝访问
// ...
}
}
// 用户组权限
// group_id = 1: 超级管理员(所有权限)
// group_id = 2: 普通用户
// group_id = 3: 版主(前台管理权限)
十、配置说明
10.1 config.php 配置
<?php
return array(
// 数据库配置
'db' => array(
'host' => 'localhost',
'port' => 3306,
'user' => 'root',
'pass' => 'password',
'name' => 'yuanbbs',
'prefix' => 'yb_',
'charset' => 'utf8mb4'
),
// 网站配置
'site' => array(
'name' => '苗Matrix',
'url' => 'https://example.com',
'description' => '开源社区论坛系统'
),
// 邮件配置
'mail' => array(
'smtp_host' => 'smtp.example.com',
'smtp_port' => 465,
'smtp_user' => 'noreply@example.com',
'smtp_pass' => 'password',
'smtp_secure' => 'ssl'
),
// 模板配置
'template' => array(
'name' => 'default'
),
// 开发模式
'developer_mode' => false,
'debug' => false
);
?>
10.2 开发模式
// 开启开发模式
'developer_mode' => true,
// 开发模式功能:
// 1. 支持外部目录开发插件和主题
// 2. 显示详细错误信息
// 3. 禁用模板缓存
十一、常见问题
Q: 模板修改后不生效?
清理模板缓存:删除 cache/template/ 目录下的所有文件,或在 config.php 中设置 'cache_enabled' => false
Q: 插件安装后不显示?
检查 plugin.info.php 中 'enabled' 是否为 true,检查钩子函数是否正确定义(使用 function_exists 检查)
Q: CSRF验证失败?
确保表单中包含 ,确保 session_start() 已在 include/init.php 中调用
Q: 数据库操作失败?
检查 config.php 中数据库配置是否正确,检查表前缀是否匹配
Q: 如何调试SQL语句?
开启 debug 模式后,SQL错误会显示详细信息。也可以使用 $db->query() 执行原生SQL进行调试