插件开发指南
开发者开发第三方插件(非官方插件)需要进行以下声明:
EchoX 开放平台第三方插件开发者声明
本人 / 本团队(以下统称 “开发者”)自愿在 EchoX 开放平台(open.echox.cc,以下简称 “平台”)开发、发布、运营第三方插件(非官方插件,以下简称 “插件”),并郑重作出如下声明:
一、合规开发承诺
- 开发者承诺严格遵守《中华人民共和国网络安全法》《中华人民共和国个人信息保护法》《互联网信息服务管理办法》等国家法律法规及平台发布的《EchoX 开放平台隐私政策》《EchoX 开放平台服务条款》《第三方插件开发规范》等所有规则,插件开发、发布、运营全程合法合规,不违反公序良俗。
- 开发者承诺插件功能与描述一致,不开发、发布虚假功能、恶意诱导、违规引流类插件,不利用插件从事任何违法违规活动(如传播色情、暴力、赌博、反动信息,窃取用户信息,实施网络攻击等)。
二、知识产权承诺
- 开发者承诺对所开发插件拥有完整、合法的知识产权(包括但不限于版权、专利权、商标权等),或已获得知识产权权利人的明确授权,插件内容不存在抄袭、盗用、篡改他人作品 / 代码的情形。
- 若插件使用第三方开源代码 / 组件,开发者承诺遵守对应开源协议,已获得合法使用权限,不侵犯开源作者及相关方权益。
- 因插件知识产权侵权引发的一切纠纷(包括但不限于投诉、诉讼、赔偿),由开发者独立承担全部责任,与 EchoX 开放平台无关;平台因此遭受损失的,开发者需全额赔偿。
三、安全保障承诺
- 开发者承诺插件不含任何恶意代码(如病毒、木马、挖矿程序、后门程序等),不窃取、泄露、倒卖用户及平台的任何数据(包括但不限于用户账号、手机号、身份证号、论坛内容、平台接口数据等)。
- 开发者承诺插件仅收集实现核心功能所必需的信息,且收集、使用用户信息前已获得用户明确同意,严格遵守平台隐私政策要求,不超范围收集、滥用用户信息。
- 开发者承诺及时修复插件存在的安全漏洞,若因插件安全问题导致用户 / 平台数据泄露、设备受损、财产损失等,由开发者独立承担全部赔偿责任。
四、责任划分承诺
- 插件的开发、测试、发布、售后、运营等全流程由开发者独立负责,插件使用过程中产生的一切问题(包括但不限于功能异常、数据错误、兼容性问题、用户损失等),均由开发者承担全部责任,EchoX 开放平台不承担任何连带责任。
- 开发者承诺向插件使用者提供清晰的使用说明、售后联系方式,及时响应并解决用户的咨询、投诉、问题反馈,保障插件正常使用。
- 若插件涉及付费、变现等行为,开发者承诺收费标准透明、合理,不欺诈、误导用户,交易纠纷由开发者与用户自行协商解决,平台仅提供技术对接支持,不介入纠纷处理。
五、平台规则遵守承诺
- 开发者承诺接受 EchoX 开放平台对插件的审核、监管、抽检,配合平台完成插件合规性、安全性检测,若平台发现插件违反本声明或平台规则,开发者同意平台采取下架插件、冻结开发者账号、没收收益等措施。
- 开发者承诺未经平台允许,不使用 “EchoX 官方”“EchoX 认证” 等易误导用户的标识,不宣称插件与平台存在官方合作关系。
- 开发者承诺插件下架 / 停止运营前,提前 7 个工作日通知插件使用者,妥善处理用户已付费、未到期服务等问题,保障用户合法权益。
六、免责声明
开发者确认,EchoX 开放平台仅提供插件展示、分发的技术服务,不对第三方插件的合法性、安全性、功能性、可用性做任何明示或默示的担保;因使用第三方插件导致的任何损失,均与平台无关。
七、其他
- 本声明自开发者在平台提交第三方插件审核之日起生效,对开发者及所开发的所有第三方插件均具有约束力。
- 若开发者违反本声明,平台有权终止开发者的入驻资格,下架全部插件,并保留追究开发者法律责任的权利。
- 本声明未尽事宜,按照 EchoX 开放平台相关规则及国家法律法规执行。
开发者(签字):XXX
开发者账号 / 团队名称 (EchoX开放平台用户名):XXX
联系电话:XXX
日期:XX年X月X日
EchoX 论坛插件开发文档
===========================================================================
概述
===========================================================================
EchoX 论坛支持插件扩展机制,允许开发者在不修改核心代码的情况下扩展论坛功能。
===========================================================================
插件目录结构
===========================================================================
plugins/
└── 你的插件名称/ # 插件目录(英文,首字母大写)
├── plugin.json # 插件配置文件(必需)
├── hook.php # 插件钩子文件(可选)
└── ... # 其他文件(页面、CSS、JS等)
===========================================================================
快速开始
===========================================================================
1. 创建插件目录
在 plugins/ 目录下创建你的插件文件夹,例如:MyPlugin
2. 编写 plugin.json
{
"name": "我的插件",
"identifier": "MyPlugin",
"version": "1.0.0",
"author": "你的名字",
"description": "插件的简短描述"
}
3. 编写 hook.php(可选)
如果你需要在特定时机执行代码(如页面加载时),创建 hook.php 文件。
4. 创建插件页面(可选)
如果插件需要独立页面(如好友系统),可以在插件目录下创建 PHP 文件。
===========================================================================
配置文件说明
===========================================================================
plugin.json 字段说明:
| 字段 | 类型 | 必填 | 说明 |
|--------------|----------|------|----------------------------------------|
| name | string | 是 | 插件显示名称 |
| identifier | string | 是 | 插件唯一标识符(英文,与目录名一致) |
| version | string | 是 | 插件版本号,如 "1.0.0" |
| author | string | 否 | 作者名称 |
| description | string | 否 | 插件描述 |
===========================================================================
可用钩子点
===========================================================================
1. page_header - 页面头部
触发时机: 每个页面加载时,在 <body> 开始后
适用场景: 插入全局CSS、JS、顶部导航等
可用变量: 所有系统变量
调用位置: templates/header.php, mobile/includes/header.php
2. page_footer - 页面底部
触发时机: 每个页面结束前,在 </body> 前
适用场景: 插入统计代码、底部脚本、浮动按钮等
可用变量: 所有系统变量
调用位置: templates/footer.php, mobile/includes/footer.php
3. user_profile_sidebar - 用户个人中心侧边栏
触发时机: 用户个人中心页面加载时
适用场景: 添加个人中心功能区块
额外变量:
- $viewUserId - 被查看用户的ID
- $viewUser - 被查看用户的信息
调用位置: user.php
4. post_before_content - 帖子内容前
触发时机: 帖子详情页,帖子内容显示前
适用场景: 插入广告、提示信息等
额外变量:
- $post - 帖子信息数组
调用位置: post.php
5. post_after_content - 帖子内容后
触发时机: 帖子详情页,帖子内容显示后
适用场景: 插入分享按钮、相关推荐等
额外变量:
- $post - 帖子信息数组
调用位置: post.php
6. home_content - 首页内容区
触发时机: 首页加载时
适用场景: 添加首页功能区块
额外变量:
- $categories - 板块列表
- $latestPosts - 最新帖子
调用位置: index.php
7. mobile_user_card - 手机版用户卡片
触发时机: 手机版用户个人页面,用户信息卡片区域
适用场景: 在用户头像、用户名下方显示额外信息(如积分、等级等)
额外变量:
- $currentUser - 当前登录用户
- $viewUser - 被查看的用户
- $isOwnProfile - 是否查看自己的主页
- $wearingMedals - 佩戴的勋章列表
调用位置: mobile/user.php
8. mobile_user_functions - 手机版我的功能
触发时机: 手机版"我的"页面,功能菜单网格区域
适用场景: 添加功能图标按钮(如签到、任务中心等)
额外变量:
- $currentUser - 当前登录用户
- $viewUser - 被查看的用户
- $isOwnProfile - 是否查看自己的主页
调用位置: mobile/user.php
示例代码:
<?php
// 在手机版"我的功能"区域添加签到按钮
if ($hookPoint !== 'mobile_user_functions') {
return;
}
if (!$isOwnProfile) {
return; // 只在查看自己主页时显示
}
?>
<a href="/plugins/SignIn/sign.php" class="mobile-menu-item">
<div class="mobile-menu-icon" style="background: #ffebee; color: #f44336;">
<i class="fas fa-calendar-check"></i>
</div>
<span>每日签到</span>
</a>
9. mobile_user_account - 手机版账号管理
触发时机: 手机版"我的"页面,账号管理列表区域
适用场景: 添加账号管理选项(如安全设置、隐私设置等)
额外变量:
- $currentUser - 当前登录用户
- $viewUser - 被查看的用户
- $isOwnProfile - 是否查看自己的主页
调用位置: mobile/user.php
示例代码:
<?php
// 在账号管理列表添加选项
if ($hookPoint !== 'mobile_user_account') {
return;
}
?>
<a href="/plugins/MyPlugin/security.php" class="mobile-menu-list-item">
<i class="fas fa-shield-alt" style="color: #4caf50;"></i>
<span>安全中心</span>
<i class="fas fa-chevron-right" style="margin-left: auto; color: #ccc;"></i>
</a>
10. mobile_user_footer - 手机版用户页面底部
触发时机: 手机版用户页面底部,所有内容之后
适用场景: 添加统计信息、广告、额外说明等
额外变量:
- $currentUser - 当前登录用户
- $viewUser - 被查看的用户
- $isOwnProfile - 是否查看自己的主页
调用位置: mobile/user.php
===========================================================================
系统变量列表
===========================================================================
在 hook.php 中可以直接使用以下变量:
【基础变量】
| 变量名 | 类型 | 说明 |
|--------------|----------|----------------------------------------|
| $hookPoint | string | 当前钩子点名称 |
| $siteUrl | string | 网站URL |
| $db | object | 数据库实例 |
| $user | array/null | 当前登录用户信息 |
【用户相关】
| 变量名 | 类型 | 说明 |
|--------------|----------|----------------------------------------|
| $isLoggedIn | bool | 是否已登录 |
| $isAdmin | bool | 是否管理员 |
| $isSuperAdmin| bool | 是否超级管理员 |
| $userId | int | 当前用户ID |
【请求相关】
| 变量名 | 类型 | 说明 |
|--------------|----------|----------------------------------------|
| $currentUrl | string | 当前完整URL |
| $requestMethod| string | HTTP方法 (GET/POST) |
| $getParams | array | GET参数数组 |
| $postParams | array | POST参数数组 |
| $requestUri | string | 请求URI |
| $userAgent | string | 用户浏览器标识 |
| $userIp | string | 用户IP地址 |
【页面信息】
| 变量名 | 类型 | 说明 |
|--------------|----------|----------------------------------------|
| $pageTitle | string | 页面标题 |
| $isMobile | bool | 是否移动端 |
| $currentPage | array | 当前页面信息(type, filename, path等) |
【论坛统计】
| 变量名 | 类型 | 说明 |
|--------------|----------|----------------------------------------|
| $siteStats | array | 站点统计(userCount, postCount, replyCount等) |
===========================================================================
插件管理函数
===========================================================================
【插件检查】
- isPluginEnabled($identifier) - 检查插件是否启用
【用户相关】
- getCurrentUser() - 获取当前登录用户
- isLoggedIn() - 检查是否已登录
- isAdmin() - 检查是否为管理员
- isSuperAdmin() - 检查是否为超级管理员
【数据库操作】
- db() - 获取数据库实例
- db()->query($sql, $params) - 查询多条记录
- db()->queryOne($sql, $params) - 查询单条记录
- db()->execute($sql, $params) - 执行SQL
【工具函数】
- e($string) - HTML转义
- redirect($url) - 页面跳转
- setFlashMessage($type, $message) - 设置提示消息
- getFlashMessage() - 获取提示消息
- formatTime($time) - 格式化时间
- truncate($string, $length) - 截取字符串
- show404Page($message) - 显示404页面
===========================================================================
开发示例
===========================================================================
示例 1:页面底部添加浮动按钮
-------------------------------------------
plugins/FloatButton/plugin.json:
{
"name": "浮动按钮",
"identifier": "FloatButton",
"version": "1.0.0",
"author": "开发者",
"description": "在页面底部添加返回顶部按钮"
}
plugins/FloatButton/hook.php:
<?php
// 只在页面底部钩子执行
if ($hookPoint !== 'page_footer') {
return;
}
?>
<style>
.back-to-top {
position: fixed;
bottom: 30px;
right: 30px;
width: 50px;
height: 50px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
cursor: pointer;
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
z-index: 999;
}
</style>
<a href="#" class="back-to-top" onclick="window.scrollTo({top: 0, behavior: 'smooth'}); return false;">
<i class="fas fa-arrow-up"></i>
</a>
示例 2:帖子内容后添加分享按钮
-------------------------------------------
plugins/ShareButtons/plugin.json:
{
"name": "分享按钮",
"identifier": "ShareButtons",
"version": "1.0.0",
"author": "开发者",
"description": "在帖子后添加社交分享按钮"
}
plugins/ShareButtons/hook.php:
<?php
// 只在帖子内容后钩子执行
if ($hookPoint !== 'post_after_content') {
return;
}
?>
<div class="share-buttons" style="margin-top: 20px; padding-top: 20px; border-top: 1px solid #eee;">
<span style="color: #666; margin-right: 10px;">分享到:</span>
<a href="https://service.weibo.com/share/share.php?url=<?php echo urlencode($currentUrl); ?>" target="_blank" class="btn btn-sm" style="background: #e6162d; color: #fff;">
<i class="fab fa-weibo"></i> 微博
</a>
<a href="https://connect.qq.com/widget/shareqq/index.html?url=<?php echo urlencode($currentUrl); ?>&title=<?php echo urlencode($post['title']); ?>" target="_blank" class="btn btn-sm" style="background: #12b7f5; color: #fff;">
<i class="fab fa-qq"></i> QQ
</a>
</div>
示例 3:带独立页面的插件(好友系统)
-------------------------------------------
参考 plugins/Friends/ 目录下的完整实现。
===========================================================================
插件页面开发
===========================================================================
如果插件需要独立页面(如好友系统、商城等):
1. 在插件目录下创建 PHP 文件(如 friends.php)
2. 文件开头检查插件是否启用:
<?php
require_once __DIR__ . '/../../includes/functions.php';
// 检查插件是否启用
if (!isPluginEnabled('YourPlugin')) {
show404Page('该功能已禁用');
}
// 检查是否登录(如需要)
if (!isLoggedIn()) {
redirect(SITE_URL . '/login.php');
}
// 页面逻辑...
?>
3. 引入CSS(如果需要):
<?php
echo '<link rel="stylesheet" href="' . SITE_URL . '/plugins/YourPlugin/style.css">';
?>
===========================================================================
插件安装流程
===========================================================================
1. 开发插件
- 创建插件目录
- 编写 plugin.json
- 编写 hook.php(如有需要)
- 创建插件页面(如有需要)
2. 上传插件
- 将插件文件夹上传到 plugins/ 目录
3. 数据库安装(如需要)
- 创建 install.sql 或 install.php
- 运行安装脚本创建表
4. 后台安装
- 登录管理后台
- 进入"插件管理"
- 在"可用插件"中找到你的插件
- 点击"安装"
5. 启用插件
- 在"已安装插件"中找到你的插件
- 点击"启用"
===========================================================================
⚠️ 重要注意事项
===========================================================================
1. 函数重复定义问题(重要!)
问题: 同一个页面可能多次调用 load_plugins(),导致 hook.php 被多次包含。
后果: 如果定义了 PHP 函数,会出现 "Cannot redeclare function" 致命错误。
解决方案: 所有 PHP 函数必须用 function_exists() 包裹:
// ❌ 错误写法 - 会导致重复定义错误
function myPluginFunction() {
// ...
}
// ✅ 正确写法 - 防止重复定义
if (!function_exists('myPluginFunction')) {
function myPluginFunction() {
// ...
}
}
推荐做法:
- 如果不需要定义 PHP 函数,直接在 hook.php 中输出 HTML/CSS/JS
- 如果需要定义函数,确保使用 function_exists() 检查
2. 钩子点判断
推荐做法: 在 hook.php 开头判断当前钩子点:
// 方法1: 只在特定钩子执行
if ($hookPoint !== 'page_footer') {
return;
}
// 方法2: 支持多个钩子
if (!in_array($hookPoint, ['page_header', 'page_footer'])) {
return;
}
// 方法3: switch 语句处理不同钩子
switch ($hookPoint) {
case 'page_header':
// ...
break;
case 'page_footer':
// ...
break;
}
3. 防止直接访问
推荐做法: 在 hook.php 开头检查变量是否存在:
<?php
// 防止直接访问
if (!isset($hookPoint)) {
return;
}
// 或者
if (!defined('SITE_URL')) {
exit('Access Denied');
}
?>
4. 路径处理
问题: 插件内部引用文件时,路径可能不正确。
解决方案:
<?php
// ✅ 正确做法 - 使用动态计算路径
$pluginUrl = '/plugins/YourPlugin';
// 或者使用 SITE_URL 常量
$pluginUrl = SITE_URL . '/plugins/YourPlugin';
// 引用JS文件
<script src="<?php echo $pluginUrl; ?>/script.js"></script>
// 引用API接口
fetch('<?php echo $pluginUrl; ?>/api/something.php')
?>
5. 插件禁用保护
问题: 插件被禁用后,直接访问插件页面会报错。
解决方案: 在插件页面开头检查:
<?php
require_once __DIR__ . '/../../includes/functions.php';
// 检查插件是否启用
if (!isPluginEnabled('YourPlugin')) {
show404Page('该功能已禁用');
}
?>
6. 移动端适配
推荐做法: 使用 $isMobile 变量判断当前环境:
<?php
if ($isMobile) {
// 移动端代码
} else {
// PC端代码
}
?>
7. 安全性
- 不要信任用户输入: 所有输出使用 e() 函数转义
- SQL注入防护: 使用参数化查询 $db->query($sql, $params)
- XSS防护: 不要直接输出用户提交的内容
8. 性能优化
- 按需加载: 只在需要的钩子点执行代码
- 减少数据库查询: 缓存重复使用的数据
- CSS/JS优化: 避免加载不必要的资源
9. 调试技巧
- 查看错误日志: 检查 PHP 错误日志
- 使用 error_log: error_log('调试信息: ' . var_export($var, true));
- 浏览器开发者工具: 检查网络请求和控制台错误
10. 常见错误
| 错误信息 | 原因 | 解决方案 |
|---------------------------|----------------------|---------------------------------------|
| Cannot redeclare function | 函数重复定义 | 使用 function_exists() 包裹 |
| Undefined variable | 变量未定义 | 检查钩子点是否正确 |
| 404 Not Found | 路径错误 | 检查插件目录名和引用路径 |
| Access Denied | 直接访问 hook.php | 添加访问检查 |
| 插件不生效 | 未启用或钩子点错误 | 检查后台状态和钩子点名称 |
===========================================================================
完整示例:带函数定义的插件
===========================================================================
plugins/MyPlugin/hook.php:
<?php
/**
* 我的插件 - hook.php
*/
// 防止直接访问
if (!isset($hookPoint)) {
return;
}
// ============================================
// 函数定义(使用 function_exists 防止重复定义)
// ============================================
if (!function_exists('myPluginGetData')) {
/**
* 获取插件数据
*/
function myPluginGetData($userId) {
$db = Database::getInstance();
return $db->queryOne("SELECT * FROM my_plugin_data WHERE user_id = ?", [$userId]);
}
}
if (!function_exists('myPluginRenderWidget')) {
/**
* 渲染插件组件
*/
function myPluginRenderWidget($data) {
// ...
}
}
// ============================================
// 根据钩子点执行不同逻辑
// ============================================
switch ($hookPoint) {
case 'page_header':
// 加载CSS
?>
<link rel="stylesheet" href="<?php echo SITE_URL; ?>/plugins/MyPlugin/style.css">
<?php
break;
case 'page_footer':
// 显示浮动按钮
?>
<a href="<?php echo SITE_URL; ?>/plugins/MyPlugin/page.php" class="my-plugin-float-btn">
<i class="fas fa-star"></i>
</a>
<?php
break;
}
?>
===========================================================================
更新日志
===========================================================================
v1.2.0 (2026-02-16)
- 添加详细的注意事项说明
- 添加函数重复定义问题的解决方案
- 添加完整示例代码
v1.1.0 (2026-02-12)
- 添加多个钩子点(page_header, page_footer, user_profile_sidebar等)
- 添加丰富的系统变量支持
- 添加插件访问控制(禁用后自动404)
- 添加插件管理函数
v1.0.0
- 初始版本发布
- 支持基础钩子机制
===========================================================================
文档版本: 1.2
最后更新: 2026-02-16
===========================================================================