RyeBlogRye

RyeBlog 插件开发指南:接口、钩子与完整示例

2026-08-19 · 在线文档 · #博客· #教程

RyeBlog 采用轻量插件机制:一个目录 = 一个插件,无需注册表、无需 Composer,把插件目录放到 usr/plugins/ 并在后台启用即可。

一、插件目录结构

usr/plugins/<插件名>/
└── Plugin.php        # 唯一必需文件(类文件)
<?php
/**
 * @Title    防垃圾评论
 * @Desc     多层无感防垃圾:蜜罐、时间陷阱、链接数限制…
 * @Version  1.0.0
 * @Author   RyeBlog Team
 */
class Plugin_spam_guard { ... }

二、生命周期钩子

插件类中的静态方法会被系统在对应时机自动调用:

| 方法 | 时机 |
|---|---|
| activate() | 后台启用插件时(常用于建表、初始化选项) |
| deactivate() | 后台停用插件时(用于清理,可返回 false 中止停用) |
| config() | 后台「插件配置」页显示配置表单(返回 HTML) |
| saveConfig($post) | 配置表单提交时保存 |

activate() 里建议用 dbQuery() 建表(自动适配表前缀):

public static function activate()
{
    dbQuery('CREATE TABLE IF NOT EXISTS vd_my_data (
        id INT AUTO_INCREMENT PRIMARY KEY,
        name VARCHAR(100) NOT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4');
    setOption('my_plugin_enabled', '1');
    return true;
}
注意:SQL 里的 vd_ 前缀会被自动转换为站点实际前缀,请勿使用裸 db()->exec()

三、钩子(Hook)系统

doHook('名称', $参数) 会调用所有已启用插件中同名的静态方法,返回值的拼接结果。核心预留的钩子:

| 钩子 | 触发位置 | 参数 |
|---|---|---|
| nav_top | 顶栏导航 | — |
| home_after | 首页列表之后 | — |
| page_replace | 独立页渲染前 | $page(返回非空字符串则替换整页) |
| post_content_after | 文章正文之后 | $post |
| articleFooter | 文章底部 | $post |
| comment_form_extra | 评论表单内 | —(注入蜜罐/时间戳等) |
| comment_check | 评论提交检查 | $_POST(返回非空字符串 = 拒绝原因) |

示例——在文章底部追加版权信息:

class Plugin_post_copyright
{
    public static function post_content_after($post)
    {
        return '<div style="margin-top:20px;padding:12px;background:#f4fcf8;border-radius:8px">
            本文由「' . esc($post['author']) . '」原创发布,转载请注明出处。</div>';
    }
}

四、核心 API(插件里可直接调用)

五、完整示例:防垃圾评论插件(已发布到云端)

官方 spam-guard 插件展示了插件开发的全部要点:

class Plugin_spam_guard
{
    // 1. 激活:建拦截日志表 + 初始化配置
    public static function activate() {
        dbQuery('CREATE TABLE IF NOT EXISTS vd_spam_log (
            id INT AUTO_INCREMENT PRIMARY KEY,
            ip VARCHAR(45) NOT NULL, reason VARCHAR(120) NOT NULL,
            content TEXT NULL,
            created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4');
        setOption('spamguard_cfg', json_encode(['enabled'=>'1','honeypot'=>'1','time_min'=>'3','max_links'=>'2']));
        return true;
    }

    // 2. 向评论表单注入蜜罐字段
    public static function comment_form_extra($arg = null) {
        return '<input type="text" name="comment_hp" value="" tabindex="-1" autocomplete="off"
            style="position:absolute;left:-9999px;opacity:0">'
            . '<input type="hidden" name="comment_ts" value="' . time() . '">';
    }

    // 3. 提交检查:蜜罐被填 / 提交过快 → 拒绝
    public static function comment_check($arg = null) {
        $d = is_array($arg) ? $arg : $_POST;
        if (trim((string)($d['comment_hp'] ?? '')) !== '') return '提交过于频繁,请稍后再试。';
        $ts = (int)($d['comment_ts'] ?? 0);
        if ($ts > 0 && time() - $ts < 3) return '提交过于频繁,请稍后再试。';
        return ''; // 通过
    }

    // 4. 后台配置页
    public static function config() { /* 返回表单 HTML */ }
    public static function saveConfig($post) { /* 保存配置 */ }
}

六、发布到云端市场

php tools/cli_pack.php plugin <插件名> --version 1.0.0

命令会生成 cloud-release/plugins/<name>-<version>.zip 并更新 repo.json(含 SHA-256 校验)。把这两个文件放到云端仓库(默认 https://ryeblog.com/cloud/)后,全站用户都可在后台「插件 → 云端」在线安装。

← 数据导入:WordPress / Typecho 无缝迁移 RyeBlog 开发接口速查:URL、函数、表结构与钩子 →