Zibll 附加插件开发指南

预计阅读 211 分钟

🎯 何时使用本技能

  • 新建或维护依赖 zibll 子比主题的独立插件(非修改主题核心文件)
  • 需要 CSF 后台选项CSF 小工具,且必须兼容主题加载顺序
  • 开发 zibll 附加插件、子比扩展、CSF 后台、侧栏小工具或与 zibaut 并列的插件

⚠️ 核心约束(必读)

💡 重要提示:违反以下约束将导致插件无法正常工作或产生致命错误。

  1. 主题后于插件加载:任意 CSF::CSF_Widget 及依赖主题提供的函数,必须挂在 zib_require_end 内;不得在插件文件顶层直接调用(否则会因主题未加载而报错)。
  2. 插件主文件名必须与插件文件夹名完全一致(例如文件夹 zibll-additional-demo01 → 入口 zibll-additional-demo01.php)。
  3. 所有函数、选项 key、widget key、脚本 handle 使用唯一前缀,避免与主题或其他插件冲突。
  4. CSF 的 options 储存 KEY$options_key)必须全局唯一,不可与其它插件或主题重复。
  5. CSF 框架路径:主题的 CSF 框架主体代码位于 inc/codestar-framework/ 目录下,inc/csf-framework/ 仅包含小工具表单相关的 ZCSF 类。插件开发应使用 CSF::createOptions()CSF::createWidget(),这两个方法都在 codestar-framework 中定义。

主题加载顺序说明

主题在 inc/inc.php 中按以下顺序加载核心文件:

  1. inc/dependent → 依赖检测与工具函数
  2. inc/codestar-framework/codestar-framework → CSF 框架主体
  3. inc/widgets/widget-class → 小工具类封装
  4. inc/csf-framework/classes/zib-csf.class → ZCSF 小工具表单类
  5. do_action('zib_require_end')插件应挂载此钩子注册 CSF

理解加载顺序有助于避免”类未定义”错误。

🚀 快速开始

1. 创建插件目录结构

在同名 zibll-additional-demo01.php 顶部使用 WordPress 标准插件头注释,按需修改名称、版本、作者、URI、Requires PHP 等。

新建插件目录,例如 zibll-additional-demo01/

<!--?php
/**
 * Plugin Name:       子比附加示例插件
 * Plugin URI:        https://1z345.cn/
 * Description:       专为子比主题开发的附加示例插件
 * Version:           1.0.0
 * Author:            小武
 * Author URI:        https://1z345.cn/
 * Requires at least: 7.0
 * Requires PHP:      8.1
 */

if (!defined('ABSPATH')) {
    exit;
}-->

2. 主题依赖检测

在入口文件早期执行(在引入使用主题的代码之前):

  • get_stylesheet() != 'zibll':仅 add_action('admin_notices', ...) 提示依赖 zibll,然后 return 终止后续加载,避免前台/后台致命错误。

3. 注册激活钩子

使用 register_activation_hook() 处理启用时任务(建表、初始化选项等)。

4. 分文件组织代码

根据插件复杂度选择合适的组织结构:

  • 简单插件:逻辑可集中在入口文件
  • 复杂插件:按功能模块分子目录
your-plugin/
├── your-plugin.php          # 入口(依赖检测 + require_once)
├── inc/
│   ├── options.php          # CSF 后台选项(挂 zib_require_end)
│   ├── widget.php           # CSF 小工具(挂 zib_require_end)
│   └── ajax.php             # AJAX 处理器
└── assets/
    ├── css/
    │   └── frontend.css     # 前台样式
    └── js/
        └── frontend.js      # 前台脚本

5. CSF 后台选项配置

⚠️ 关键:必须将注册函数挂在 zib_require_end 钩子内!

  • 使用:add_action('zib_require_end', 'yourprefix_admin_csf_options');
  • 函数内先检查:if (!is_admin()) return;
  • 使用唯一 $options_key 调用 CSF::createOptions($options_key, array(...))
  • 再用 CSF::createSection / fields 定义字段;字段 id 仅限小写字母、数字、下划线
  • 复杂字段类型可参考主题内示例:wp-content/themes/zibll/inc/options/admin-options.php

完整模板:

function yourprefix_admin_csf_options()
{
    if (!is_admin()) {
        return;
    }

    $options_key = 'yourplugin_options';

    CSF::createOptions($options_key, array(
        'menu_title'         => __('你的插件设置', 'your-textdomain'),
        'menu_slug'          => $options_key,
        'framework_title'    => __('插件名称', 'your-textdomain'),
        'show_in_customizer' => false,
        'theme'              => 'light',
    ));

    CSF::createSection($options_key, array(
        'id'    => 'basic',
        'title' => __('基础设置', 'your-textdomain'),
        'icon'  => 'fa fa-fw fa-cog',
        'fields' => array(
            array(
                'id'      => 'enabled',
                'type'    => 'switcher',
                'title'   => __('启用功能', 'your-textdomain'),
                'default' => true,
            ),
            array(
                'id'      => 'text_field',
                'type'    => 'text',
                'title'   => __('文本输入', 'your-textdomain'),
                'default' => '',
            ),
        ),
    ));

add_action(‘zib_require_end’, ‘yourprefix_admin_csf_options’);


### CSF 选项保存钩子机制

CSF 框架在保存选项时会触发以下钩子(以 `$options_key = 'arc_options'` 为例):

| 钩子名称 | 类型 | 用途 | 示例 |
|---------|------|------|------|
| `csf_{$unique}_save` | filter | 保存前验证/修改数据 | `add_filter('csf_arc_options_save', ...)` |
| `csf_{$unique}_saved` | action | 保存后执行操作(如清缓存) | `add_action('csf_arc_options_saved', ...)` |

**完整示例:**
```php
// 保存前验证
add_filter('csf_arc_options_save', function($data) {
    // 验证逻辑
    if (empty($data['required_field'])) {
        add_settings_error('arc_options', 'required_missing', __('必填字段不能为空', 'textdomain'));
    }
    return $data;
});

// 保存后清除缓存
add_action('csf_arc_options_saved', function() {
    wp_cache_delete('arc_plugin_options', 'arc_plugin');
});

⚠️ 常见错误:不要猜测钩子名称如 csf_validate_arc_optionscsf_save_options_arc_options,正确格式始终是 csf_{$unique}_savecsf_{$unique}_saved

6. 读取主题选项

使用主题提供的 _pz() 函数读取后台设置(带静态缓存,性能极佳):

  • 实现 yourprefix_get_option($key, $default = false):内部 static $options,首次 get_option($options_key),返回 $options[$key] ?? $default
  • $options_key 与 CSF 注册处必须一致。
function yourprefix_get_option($key, $default = false)
{
    static $options = null;
    if ($options === null) {
        $options = get_option('yourplugin_options');
    }
    return isset($options[$key]) ? $options[$key] : $default;
}

7. 创建 CSF 小工具

⚠️ 同样必须挂在 zib_require_end 钩子内!

⚠️ 重要说明Zib_CFSwidget完全废弃(源码注释明确说明”此对象已经没有使用,为了兼容旧版插件保留”),内部直接委托给 CSF::createWidget()CSF_Widget

  • 新插件必须使用CSF::createWidget($widget_key, array(...))
  • 旧代码兼容Zib_CFSwidget::create($widget_key, array(...)) 仍可工作,但不推荐使用
  • 注册:add_action('zib_require_end', 'yourprefix_widget_create');
  • CSF::createWidget($widget_key, array(...))Zib_CFSwidget::create($widget_key, array(...))$widget_key 自定且唯一。
  • 前端输出函数名必须等于 create 的第一个参数 $widget_key
  • 输出模板:使用 CSF_Widget::show_class($instance) 做显示控制;内容直接 echo HTML 即可;文本输出使用 esc_html / 合适转义。

完整模板:

// 注册小工具(必须在 zib_require_end 内)
function yourprefix_widget_create()
{
    CSF::createWidget('yourprefix_demo_widget', array(
        'title'       => __('你的小工具', 'your-textdomain'),
        'classname'   => 'yourprefix-demo-widget',
        'description' => __('小工具描述', 'your-textdomain'),
        'width'       => '350px',
        'fields'      => array(
            array(
                'id'      => 'title',
                'type'    => 'text',
                'title'   => __('标题', 'your-textdomain'),
                'default' => __('默认标题', 'your-textdomain'),
            ),
            array(
                'id'      => 'show_bg',
                'type'    => 'switcher',
                'title'   => __('显示背景', 'your-textdomain'),
                'default' => true,
            ),
        ),
    ));
}
add_action('zib_require_end', 'yourprefix_widget_create');

// 前端输出(函数名 = widget_key)
function yourprefix_demo_widget($args, $instance)
{
    $show_bg = !empty($instance['show_bg']);
    $title   = $instance['title'] ?? '';

    echo '<div class="clearfix">';
    if ($show_bg) {
        echo '<div class="zib-widget nobottom notop">';
    }
    if ($title) {
        echo '<h4 class="widget-title">' . esc_html($title) . '</h4>';
    }
    echo '<div class="muted-box padding-10">你的内容</div>';
    if ($show_bg) {
        echo '</div>';
    }
    echo '</div>';
}

// 可选:显示条件过滤
function yourprefix_demo_widget_is_show($show_class, $args, $instance)
{
    if (empty($instance['title'])) {
        return false;
    }
    return $show_class;
}

8. 引入前端资源

前台样式与脚本

  • 典型目录:assets/css/assets/js/
  • 前台:add_action('wp_enqueue_scripts', ...)wp_enqueue_style / wp_enqueue_scriptplugin_dir_url(__FILE__),版本号与插件一致)。
  • 后台:add_action('admin_enqueue_scripts', ...)
  • 脚本依赖按需声明(如 array('jquery'));主题在 zib-theme.php:1044-1082 中重新注册了 jquery(主题目录 js/libs/jquery.min.js),插件与主题并存时勿假设 WP 默认 jQuery CDN 路径。
  • CSS 加载顺序建议:声明依赖 array('main') 确保在主题 main.css 之后加载。
function yourprefix_enqueue_assets()
{
    $url = plugin_dir_url(__FILE__);
    $ver = YOURPLUGIN_VERSION;

    wp_enqueue_style('yourprefix-frontend', $url . 'assets/css/frontend.css', array('main'), $ver);
    wp_enqueue_script('yourprefix-frontend', $url . 'assets/js/frontend.js', array('jquery'), $ver, true);
    wp_localize_script('yourprefix-frontend', 'yourprefix_var', array(
        'ajax_url' => admin_url('admin-ajax.php'),
        'nonce'    => wp_create_nonce('yourprefix_nonce'),
    ));
}
add_action('wp_enqueue_scripts', 'yourprefix_enqueue_assets');

🔐 AJAX 安全标准

所有 AJAX 请求必须遵循以下安全规范:

所有插件自增的 AJAX 接口都应遵循以下安全模式:

// 注册(公开接口才加 nopriv)
add_action('wp_ajax_yourprefix_action', 'yourprefix_ajax_handler');
// add_action('wp_ajax_nopriv_yourprefix_action', 'yourprefix_ajax_handler'); // 仅需公开时取消注释

function yourprefix_ajax_handler()
{
    // 1. Nonce 验证
    check_ajax_referer('yourprefix_nonce', 'nonce');

    // 2. 权限检查
    if (!current_user_can('read')) {
        wp_send_json_error(__('权限不足', 'your-textdomain'), 403);
    }

    // 3. 获取并清理参数
    $data = isset($_POST['data']) ? sanitize_text_field(wp_unslash($_POST['data'])) : '';

    // 4. 业务逻辑
    // ...

    // 5. 返回
    wp_send_json_success(array('result' => $data));
}

关键注意点:

  • 非公开接口(需要登录)不要注册 wp_ajax_nopriv_* 钩子。
  • 公开接口(如查询类)必须同时注册 wp_ajax_*wp_ajax_nopriv_*,并在回调内做权限分级。
  • nonce 应通过 wp_localize_script 注入到 JS 变量中,前端 AJAX 时携带。
  • 主题内置的 zib_ajax() 会自动处理 nonce(通过 form-data 属性或 window.captcha),插件自定义接口应自行管理 nonce。

📚 主题 API 速查表

inc/ 目录常用函数

以下为在已启用 zibll 前提下可用的常用入口;升级主题后请以源码为准,并可在 inczibpay 下用 grep 自行补充。

主题选项

  • _pz($name, $default = false, $subname = '') — 读取 get_option('zibll_options'),带静态缓存;嵌套配置用 $subname。定义见 inc/dependent.php:112
  • _spz($name, $value) — 写回 zibll_options 中单键(覆盖式合并需谨慎,优先用 CSF/后台改主题设置)。定义见 inc/dependent.php:131

用户系统(inc/functions/user/

函数文件用途
zib_get_user_center_link($class, $text)user.php用户中心页 <a> HTML
zib_get_user_center_url($type, $tab)user.php用户中心 URL($type: order/message/settings 等)
zib_get_user_id($id_or_email)zib-theme.php:539从 ID/email/对象获取用户 ID
zib_get_data_avatar($user_id, $size)zib-theme.php获取头像 HTML(含懒加载)
zib_get_user_meta($user_id, $key, $single)dependent.php读取用户 meta
zib_user_is_ban($user_id)user-ban.php是否被封禁
zib_get_user_ban_info($user_id)user-ban.php封禁详情
zib_get_user_ban_info_modal($user_id)user-ban.php封禁信息弹窗 HTML
zib_get_user_ban_appeal_modal($user_id)user-ban.php申诉弹窗 HTML
zib_user_checkin($user_id)user-checkin.php执行签到
zib_user_is_checkined($user_id)user-checkin.php今日是否已签到
zib_get_user_checkin_btn(...)user-checkin.php签到按钮 HTML
zib_get_user_checkin_details_modal($user_id)user-checkin.php签到详情弹窗
zib_add_user_medal($user_id, $medal_name, $remarks)user_medal.php添加勋章
zib_get_user_medal_info_modal($user_id)user.php (modal)勋章信息弹窗
zib_get_user_auth_apply_modal(...)user-auth.php认证申请弹窗
zib_get_user_auth_info_modal(...)user-auth.php认证信息弹窗
zib_get_user_card_box($user_id)user.php (card)用户悬浮卡片
zib_get_user_badges($user_id)functions.php:482用户徽标 HTML
zib_get_user_follow(...)zib-theme.php:2187关注按钮
zib_get_user_favorite_count($author_id)zib-theme.py:1318收藏计数

用户中心扩展点(filter):

  • zib_user_can($capability) — 统一能力判断
  • zib_user_center_page_sidebar_button_1_args / _2_args — 用户中心侧栏按钮配置(数组,可追加按钮)
  • zib_user_center_page_sidebar — 用户中心侧栏内容
  • user_show_name — 显示名
  • user_name_badge / user_avatar_badge / user_count_badges — 名称/头像/数量徽标
  • user_medal_args — 勋章参数
  • user_center_account_setup — 账户设置区
  • user_sidebar_statistics_args — 侧栏统计

URL 与工具

  • zib_get_current_url() — 当前页面完整 URL。inc/functions/functions.php
  • zib_get_admin_ajax_url($action = false, $query_arg = array()) — 拼装 admin-ajax.php 链接。
  • zib_get_lazy_attr($size, $is_other = false) — 图片懒加载属性。inc/functions/zib-tool.php
  • zib_get_time_ago($timestamp) / zib_get_time_remaining($end) / zib_get_time_spend($start, $end) — 时间文案。
  • zib_is_show_sidebar() — 是否显示侧栏(结果可走 zib_is_show_sidebar filter)。
  • zib_get_theme_mode() — 亮/暗等(可走 zib_theme_mode filter)。

UI 组件(PHP 输出 HTML)

模态框(Modal)

zib_modal($args) — 构建 Bootstrap 3 模态框。inc/functions/functions.php:992

zib_modal(array(
    'id'              => 'my-modal-id',
    'class'           => 'modal-sm',
    'colorful_header' => true,
    'header_class'    => 'jb-blue',
    'header_icon'     => '<i class="fa fa-info-circle"></i>',
    'title'           => '标题',
    'content'         => '内容 HTML',
    'buttons_align'   => 'right',
    'buttons'         => array(
        array(
            'text'    => '确定',
            'class'   => 'but c-green',
            'data'    => array('dismiss' => 'modal'),
        ),
    ),
    'buttons_class'   => 'but radius',
));

其他模态相关函数:

函数用途
zib_get_blank_modal($args)空白模态容器(仅 header + body 容器)
zib_get_blank_modal_link($text, $config)触发空白模态的 <a> 链接
zib_get_refresh_modal_link($text, $config)刷新内容模态链接
zib_get_add_modal_link($text, $config)追加内容模态链接
zib_get_modal_colorful_header($class, $icon, $content, $close_btn)彩色头部 HTML 片段
zib_get_report_modal($post_id)举报弹窗
zib_get_rewards_modal($post_id)打赏弹窗
zib_get_user_auth_apply_modal($user_id)认证申请弹窗
zib_get_user_ban_appeal_modal($user_id)封禁申诉弹窗
zib_get_user_checkin_details_modal($user_id)签到详情弹窗
zib_get_user_medal_info_modal($user_id)勋章详情弹窗

Tab 导航

  • zib_get_ajax_tab($tabs, $active, $args) — AJAX Tab 切换组件。返回包含 .ajax-tab 容器的 HTML。
  • zib_get_main_tab_nav($tabs, $active) — 主导航 Tab(用于搜索/作者等页)。
  • zib_get_search_main_tab_nav(...) / zib_get_search_tab_nav_filter(...) — 搜索页 Tab。

提示 / 公告

zib_notice($args, $echo = true) — 公告轮播条(swiper)。functions.php:882

zib_notice(array(
    'class'    => 'c-blue',
    'interval' => 5000,
    'notice'   => array(
        array('title' => '公告1', 'icon' => 'fa fa-bullhorn', 'href' => 'https://...'),
        array('title' => '公告2', 'icon' => 'fa fa-info-circle'),
    ),
));
  • zib_system_notice() — 页脚自动弹出系统通知模态(由主题选项控制,插件一般不需直接调用)。

链接生成器

函数用途
zib_get_post_edit_link($post_id)编辑文章链接
zib_get_report_link($post_id, $class, $text)举报链接
zib_get_refresh_modal_link($text, $config)刷新模态触发链接
zib_get_msg_all_readed_link($class, $text)全部已读链接
zib_get_user_auth_*_link(...)用户认证相关链接
zib_get_user_ban_*_link(...)用户封禁相关链接
zib_get_url_link($url, $text, $class)通用外链

卡片组件

  • zib_icon_card($args) — 图标卡片(图标+标题+描述+链接)。
  • zib_get_user_card_box($user_id) — 用户悬浮卡片。
  • zib_get_user_card_lists($user_id) / zib_get_user_card_post($user_id) — 卡片内的列表/文章。

移动底栏

  • filter footer_tabbar — 底部导航栏按钮配置
  • zib_get_footer_tabbar_btn($args) — 单个底栏按钮
  • zib_get_single_footer_tabbar() — 文章页底栏

ZibPay(zibpay/functions/

函数用途
zibpay_is_paid($post_id, $user_id = 0)是否已具备文章付费权益
zibpay_get_post_paid_data_by_user($post_id, $user_id)付费状态细节(按用户)
zibpay_get_post_paid_data_by_order_num($order_num)付费状态细节(按订单号)
zibpay_get_order_title($order)订单标题文案
zibpay_get_order_status_name($status)订单状态名
zibpay_get_pay_type_name($type)支付方式名
zibpay_get_payment_methods()可用支付方式列表
zibpay_get_initiate_pay_input($order)发起支付按钮 HTML
zibpay_get_admin_shop_url()后台商城 URL
zibpay_get_admin_shop_order_url()后台订单 URL

发现更多: 在主题内执行 grep -rn "^function zib_" inc/ zibpay/ 或按文件名浏览(如 zib-single.phpzib-header.php)。

常用动作钩子 do_action

核心 / 生命周期

钩子位置/用途参数
zib_require_endinc/inc.php:126 — 主题加载链结束
zibll_update_notices主题更新后提示$theme_version
zibll_new_install_notices主题新安装提示$theme_version

单篇 / 内容

钩子位置/用途参数
zib_single_before单篇模板开头
zib_single_after单篇模板结尾
zib_single_box_content_before单篇内容盒之前
zib_single_box_content_after单篇内容盒之后
zib_posts_content_before正文区域之前$post
zib_posts_content_after正文区域之后$post
zib_article_content_after正文输出之后$post
zib_pre_insert_postBBS 等发帖写入数据库前$insert_args / $post_args
zib_frontend_set_save前台编辑保存$object_data, $type
zib_bbs_posts_content_after论坛帖正文之后$post

作者 / 用户中心

钩子位置/用途参数
zib_author_main_content作者页主内容区
zib_use_invit_code邀请码使用成功$user_id, $invit_code_obj
user_checkined签到成功后(由签到动作触发)
user_add_medal添加勋章后(由勋章动作触发)
user_remove_medal移除勋章后(由勋章动作触发)
updata_user_ban更新封禁状态后(由封禁动作触发)

私信 / 消息

钩子位置/用途参数
zib_add_message发送私信前$values
zib_update_message更新私信$values
zib_message_readed已读私信$id, $_user_id
zib_message_all_readed全部已读$where, $user_id
zib_message_set_status设置消息状态$id, $values
zib_message_set_status_batch批量设状态$where, $values

商城 / 订单

钩子位置/用途参数
zib_shop_init商城初始化
zibpay_download_before付费下载前$post_id, $down_id, $paid, $file_url, $file_local
order_created订单创建后订单对象
payment_order_success支付成功后订单对象
order_closed订单关闭后订单 ID
order_refunded订单退款后订单 ID
save_order_meta保存订单 meta$order_id, $key, $value
add_order_meta新增订单 meta同上
update_order_meta更新订单 meta同上
delete_order_meta删除订单 meta同上
delete_order删除订单订单 ID
pay_transfer余额转账转账数据
user_apply_withdraw申请提现提现数据
withdraw_process提现处理处理数据
withdraw_process_newmsg提现新消息消息数据

BBS / 社区

钩子位置/用途参数
bbs_favorite_posts收藏帖子相关数据
bbs_follow_plate关注版块版块数据
bbs_home_tab_content_top论坛首页 Tab 顶部
bbs_home_tab_content_bottom论坛首页 Tab 底部
bbs_posts_essence_set设精华帖子数据
bbs_posts_topping_set置顶帖子数据
bbs_single_footer帖子底部帖子数据
posts_is_hot设热门帖子数据
posts_plate_move移动版块帖子数据
plate_is_hot版块热门版块数据
answer_adopted采纳答案回答数据
comment_is_hot评论热门评论数据
shop_favorite_product收藏商品商品数据
shop_product_page_content_after商品页内容后商品数据
author_points_income积分收入积分数据

小工具

钩子位置/用途参数
zib_cfswidget_echo_before侧栏模块输出前包裹$args
zib_cfswidget_echo_after侧栏模块输出后包裹$args

常用过滤钩子 apply_filters

主题全局

钩子用途
zib_temp_dir临时目录(与常量 ZIB_TEMP_DIR 一致)
zib_is_show_sidebar是否显示侧栏
zib_theme_mode主题色模式(light/dark 等)
zib_theme_mode_button_positions模式切换按钮位置
zib_add_bodyclass追加 body class
zib_get_excerpt摘要文本
zib_widget_title小工具标题
zib_float_right右下角浮动按钮 HTML
zib_nav_radius_button导航区域圆形按钮
zib_user_can统一能力判断 $capability
zib_oauth_login_urlOAuth 登录 URL
zib_js_i18n_strings前台 JS i18n 字符串
zib_admin_js_i18n_strings后台 JS i18n 字符串
footer_tabbar移动底栏按钮配置

用户中心

钩子用途
zib_user_center_page_sidebar用户中心侧栏内容
zib_user_center_page_sidebar_button_1_args侧栏按钮组 1 配置
zib_user_center_page_sidebar_button_2_args侧栏按钮组 2 配置
user_show_name显示名
user_name_badge名称徽标
user_avatar_badge头像徽标
user_count_badges数量徽标
user_medal_args勋章参数
user_center_account_setup账户设置区
user_sidebar_statistics_args侧栏统计参数
user_page_header_desc用户页头部描述
user_checkin_detail_maximum签到详情最大值

前台发布 / 表单

钩子用途
zib_frontend_set_input_array前台发布表单字段数组
zib_frontend_set_input_html前台发布表单字段 HTML
zib_add_message_values发私信前数据处理

ZibPay 付费

钩子用途
zibpay_is_show_paybutton是否展示付费按钮
zibpay_posts_pay_box文章付费区域 HTML
zibpay_posts_paid_box已购区域 HTML
zibpay_payment_methods支付方式列表
zibpay_order_title订单标题
zibpay_initiate_paysdk发起支付 SDK
zibpay_initiate_{$sdk}发起指定 SDK 支付
zibpay_is_allow_balance_pay是否允许余额支付
zibpay_is_allow_card_pass_pay是否允许卡密支付
zibpay_card_pass_payment_desc卡密支付描述
pay_download_paid_data下载数据权限
zibpay_download_file_local本地下载路径
pre_order_create_data创建订单前置数据
initiate_order_data_type_{$type}指定类型订单数据
not_repeat_create_order_type不重复创建的订单类型
pay_order_price_is_allow_0允许 0 元订单
hidecontent_is_show隐藏内容是否显示
hidecontent_payshow_hide_content付费隐藏内容
tourists_pay_is_allow游客是否可购买
tourists_pay_cookie_days游客购买 cookie 天数
zib_add_pay_meta_box_args文章编辑付费框参数
zib_add_pay_meta_box_meta文章编辑付费框 meta

订单 UI

钩子用途
user_order_list_card订单列表卡片 HTML
user_order_details_modal订单详情弹窗
user_page_order_tabs订单页 Tab
user_order_card_btns订单卡片按钮
user_order_details_footer_left详情底部左侧
user_order_details_footer_right详情底部右侧

BBS / 社区

钩子用途
bbs_home_tab_options论坛首页 Tab 选项
bbs_home_tab_content_plate_before首页版块前
bbs_home_tab_content_plate_after首页版块后
bbs_plate_tab_options版块 Tab 选项
bbs_plate_order_options版块排序选项
bbs_posts_order_options帖子排序选项
bbs_single_fixed_btns帖子固定按钮
bbs_user_score_deduct_max扣分上限
bbs_user_score_extra_max加分上限
bbs_is_hot_plate热门版块判断
bbs_is_hot_posts热门帖子判断

作者 / 评论

钩子用途
author_header_drop_lists作者头部下拉菜单
author_header_identity作者身份标识
author_header_more_btn作者头部更多按钮
author_main_tabs_array作者主页 Tab 数组
author_main_tab_{$key}指定 Tab 内容
author_favorite_types收藏类型
author_favorite_lists_{$type}指类型收藏列表
author_tab_favorite_count收藏计数
comments_action_lists评论操作列表
comments_user_name_badge评论用户名徽标
comment_header评论头部
comment_footer_info评论底部信息
comment_topping_enabled是否允许评论置顶
comment_edit_enabled是否允许编辑评论
mag_ctnter_main_tabs_array用户中心主 Tab
user_ctnter_main_tabs_array同上(别名)
search_main_tabs_array搜索主 Tab
search_types搜索类型
search_orderby_array搜索排序
search_facets_datas搜索筛选数据
new_add_btns_options发布按钮选项
new_add_btns_{$key}指定发布按钮
frontend_set_switch前台编辑开关
is_close_signin关闭登录
is_close_signup关闭注册
is_can_roles允许角色
hascaps_roles_lists能力角色列表
integral_add_options积分增加选项
page_max_width页面最大宽度
single_show_breadcrumbs显示面包屑
shop_auto_delivery_content自动发货内容
is_shop_cart_page是否购物车页
widget_form_callback小工具表单回调
widget_import_templates小工具导入模板
widget_is_show_{$key}小工具是否显示
message_cats消息分类

💻 前端开发规范

复用主题 main.js 全局 API

主题前台脚本链:_load_scriptszib-theme.php:1044)注册 jquerybootstraploader.jsjs/loader.js,内部 tbquire 再异步加载 main.js)。main.js 体量大,集成懒加载(lazySizes)、轮播、播放器、大量委托事件等。附加插件应优先调用已有全局函数,避免重复实现。

window._win(PHP 注入 + JS 补全)

对象首段由主题在页脚内联脚本赋值:zib-footer.php:65-110window._win = { ... }

完整字段清单:

字段类型说明
viewsstring当前文章 ID(仅单篇有值,否则空)
wwwstring站点 URL (home_url())
uristring主题目录 URL
verstring主题版本号
imgboxstring是否启图片灯箱 ("true"/"false")
imgbox_typestring灯箱类型 ("group"/"single")
imgbox_thumbsstring是否显示缩略图
imgbox_zoomstring是否显示放大
imgbox_fullstring是否全屏
imgbox_playstring是否播放
imgbox_downstring是否下载
sign_typestring登录方式
signin_urlstring登录 URL
signup_urlstring注册 URL
ajax_urlstringadmin-ajax.php URL
ajaxpagerstring分页方式
ajax_triggerstring“加载更多” 文案
ajax_nomorestring“没有更多了” 文案
qj_loadingstring“加载中…” 文案
highlight_kgstring代码高亮开关
highlight_hhstring高亮行高
highlight_btnstring高亮按钮
highlight_ztstring高亮主题
upload_img_sizestring上传图片大小限制
upload_video_sizestring上传视频大小限制
upload_file_sizestring上传文件大小限制
upload_extstring允许上传的扩展名
user_upload_noncestring上传 nonce
post_action_noncestring点赞/收藏等 action nonce
is_split_uploadstring分片上传开关
split_minimum_sizestring分片最小尺寸
comment_upload_imgstring评论上传图片开关
translate_configstring翻译配置 JSON
i18nobject前台 i18n 字符串对象

main.js 加载后补充的字段:

  • _win.bd → jQuery body 对象
  • _win.window → jQuery window 对象
  • _win.is_signinbody 是否含 logged-in class

编写插件 JS 时若仅读配置,可在 jQuery(function($){ ... }) 内使用 _win.ajax_url;若依赖 _win.bd,须在主题主逻辑跑了之后(通常同一 document ready 即可)。

AJAX 与提示(优先复用)

API作用要点
zib_ajax(_this, data, success, noty, no_loading)admin-ajax.php 的通用提交_this 为触发按钮 jQuery 对象;未传 data 时会从父级 form serializeObject(),或用 form-action / form-data 属性补 action;自动附加验证码 window.captcha(若有);成功触发 zib_ajax.success 自定义事件
$el.zib_ajax(data, success, noty, no_loading)同上$.fn.zib_ajax 封装
notyf(str, ys, time, id)右下角类 Toastyssuccess / danger / warning / load 等;error 会被映射为 dangerwindow.debounce_notyf 为防抖包装
refresh_modal(_config)动态 Bootstrap 模态支持 content / remote URL、classheightmobile_from_bottomtouch_closenew 等;与 [ajax-action] 等主题交互一致
debounce(fn, delay, immediate) / throttle(fn, delay)防抖 / 节流全局函数,滚动、resize 场景与主题一致
$.fn.serializeObject表单 → 扁平对象与主题 AJAX 表单惯例一致
lcs.get / lcs.set / lcs.remove本地存储优先 localStorage,否则回退 jQuery.cookiemain.js 内置 cookie 辅助)
zib_is_url / is_mail简单校验表单或跳转前可复用

主题独立入口(非 admin-ajax): action_ajax 等会向 _win.uri + '/action/action.php' POST,并带 _wpnonce: _win.post_action_nonce。插件自增交互应优先用 admin-ajax.php + zib_ajax 模式;若必须与主题 action 目录协议一致,再对齐其 nonce 与字段。

tbquire 异步模块清单

tbquire(['模块名'], callback) 为 loader.js 提供的异步模块加载。以下为主题已注册的模块:

模块名用途
swiperSwiper 轮播
dplayerDPlayer 视频播放器
captcha验证码
pay支付流程
imgbox图片灯箱
clipboard剪贴板复制
qrcode二维码生成
waterfall瀑布流布局
enlighterjs代码高亮
comment评论功能
message私信功能
sign-register登录注册
author作者页
mini-upload迷你上传
input-expand输入框展开
page-edit页面编辑
page-navs页面导航
page-template页面模板
poster-share海报分享
section-navs段落导航
svg-iconSVG 图标
tilt3D 倾斜效果
grade评分组件
weixin-share微信分享
translate翻译

插件若仅需极少量逻辑,不必自行再引一套 AMD;必要时在回调内写扩展。

tbquire 异步加载注意事项

tbquire 是主题定制的 RequireJS 实现,所有模块均为异步加载。使用时需注意:

// ❌ 错误:直接使用未加载的模块
tbquire(['swiper'], function() {
    // Swiper 已加载
});
// 此处 Swiper 尚未加载,不能使用 new Swiper()

// ✅ 正确:在回调内使用
tbquire(['swiper'], function() {
    new Swiper('.my-swiper', { /* config */ });
});

// ✅ 正确:检查全局对象是否存在
if (typeof Swiper !== 'undefined') {
    new Swiper('.my-swiper', { /* config */ });
}

常见模块的全局对象名:

  • swiperwindow.Swiper
  • dplayerwindow.DPlayer
  • clipboardwindow.ClipboardJS
  • qrcode → jQuery 插件 $.fn.qrcode
  • grade → jQuery 插件 $.fn.grade

插件脚本加载顺序建议:

// 依赖主题 main.js(内部会异步加载 loader.js + main.min.js)
wp_enqueue_script('your-plugin', $url, array('jquery'), $ver, true);

// JS 内安全调用主题 API
jQuery(function($) {
    // _win 已在页脚注入,可直接使用
    console.log(_win.ajax_url);
    
    // zib_ajax 需等待 main.js 加载完成
    if (typeof zib_ajax === 'function') {
        // 可以安全调用
    } else {
        // 延迟重试或监听 DOM 事件
        $(document).on('zib_main_loaded', function() {
            // main.js 加载完成后的逻辑
        });
    }
});

常用 DOM 约定(委托在 body 上)

主题在 _win.bd 上绑定了大量 click/submit:例如 [data-close][data-toggle-class][ajax-action]admin-ajax + data-nonce)、.wp-ajax-submit / [zibajax="submit"][ajax-submit] 触发表单代点提交等。插件 HTML 若沿用这些属性/类名,可无侵入复用主题行为;自定义接口应用独立类名 + 自己的 nonce

插件脚本挂载建议

  1. wp_enqueue_script(..., ['jquery'], ..., true),在回调内使用 typeof zib_ajax === 'function' 守卫后再调用(因 main.js 由 loader 异步拉起,极端情况下 ready 极早时可能尚未定义,可短延迟重试或监听首次交互)。
  2. 不要复制粘贴 main.js 整段;只依赖文档化全局 API 与 _win
  3. 需要独立 UI 时,优先使用主题已加载的 Bootstrap 3 modal/tab 类与既有 notyf 样式,保证视觉一致。

主题内置 JS 工具函数

主题在 main.js 中提供了多个实用工具函数,插件可直接调用:

函数用途示例
zib_get_url_param(name)获取 URL 参数zib_get_url_param('page')
zib_parse_url(url)解析 URL 对象zib_parse_url(window.location.href)
zib_format_number(num)格式化数字(如 1000 → 1k)zib_format_number(1234)
zib_format_time(timestamp)格式化时间戳为相对时间zib_format_time(Date.now())
zib_scroll_to(el, offset)平滑滚动到指定元素zib_scroll_to('#target', 50)
zib_is_mobile()判断是否移动端if (zib_is_mobile()) { ... }
zib_debounce(fn, delay)防抖函数zib_debounce(myFunc, 300)
zib_throttle(fn, delay)节流函数zib_throttle(myFunc, 100)

使用示例:

// 获取 URL 参数
var page = zib_get_url_param('page');

// 格式化数字
var count = zib_format_number(12345); // 返回 "12.3k"

// 平滑滚动
zib_scroll_to('.target-section', 60);

🎨 前台样式开发

复用 main.css 工具类与 CSS 变量

主题前台样式入口为 wp-content/themes/zibll/css/main.min.css(源文件 main.css,14736 行,由 _cssloader 注册)。附加插件输出 HTML(小工具、短代码、模态片段)时优先使用主题已有 class,避免硬编码色值,以自动适配亮色 / body.dark-theme

body 上的 CSS 变量(完整清单)

根变量(:root):

变量含义默认值(亮色)
--mian-max-width最大内容宽(源码拼写 mian)1200px
--posts-card-scale文章卡片缩放比例70%
--posts-list-scale列表缩放比例70%
--single-cover-scale单篇封面高度35%
--theme-color品牌主色#f04494
--focus-color聚焦色var(--theme-color)
--focus-shadow-color聚焦阴影色rgba(253,83,161,0.4)
--focus-color-opacity05聚焦色 5% 透明度
--focus-color-opacity1聚焦色 10% 透明度
--focus-color-opacity3聚焦色 30% 透明度
--key-color标题级文字#333
--main-color正文主色#4e5358
--main-shadow卡片阴影rgba(116,116,116,0.08)
--muted-color次要文字#777
--muted-2-color次要文字 2#999
--muted-3-color次要文字 3#b1b1b1
--muted-4-color次要文字 4#d2d2d2
--body-bg-color页面背景#f5f6f7
--main-bg-color卡片/面板背景#fff
--muted-bg-color弱背景#eee
--main-border-color主边框rgba(50,50,50,0.06)
--muted-border-color弱分隔线rgba(0,0,0,0.03)
--main-radius默认圆角8px
--mini-radius小圆角calc(var(--main-radius)/1.4)
--blur-bg毛玻璃背景rgba(255,255,255,0.8)
--float-btn-bg浮动按钮背景rgba(200,200,200,0.4)
--header-bg顶栏背景var(--blur-bg)
--header-color顶栏文字色var(--main-color)
--footer-bg页脚背景var(--main-bg-color)
--footer-color页脚文字色var(--muted-2-color)

暗色覆盖(body.dark-theme): 上述多数变量被覆盖为深色调(--key-color: #f8fafc--body-bg-color: #292a2d--main-bg-color: #323335 等)。

暗色模式适配标准写法:

.my-custom-element {
    background: var(--main-bg-color);
    color: var(--main-color);
    border: 1px solid var(--main-border-color);
    border-radius: var(--main-radius);
}
/* 不要这样写:
   body.dark-theme .my-custom-element { background: #323335; }
   直接用 CSS 变量即可自动适配 */

暗色模式适配完整示例

/* ✅ 推荐:使用 CSS 变量自动适配 */
.my-card {
    background: var(--main-bg-color);
    color: var(--main-color);
    border: 1px solid var(--main-border-color);
    box-shadow: 0 2px 8px var(--main-shadow);
}

.my-card:hover {
    background: var(--muted-bg-color);
}

.my-button {
    background: var(--theme-color);
    color: #fff;
}

/* ❌ 避免:硬编码色值 */
.my-card {
    background: #fff;  /* 暗色模式下不会变化 */
    color: #333;
}

/* ❌ 避免:手动写暗色覆盖(除非必要) */
body.dark-theme .my-card {
    background: #323335;  /* 与主题变量不同步,易出错 */
}

常用场景对照表:

场景推荐变量亮色默认值暗色默认值
卡片背景--main-bg-color#fff#323335
页面背景--body-bg-color#f5f6f7#292a2d
主文字色--main-color#4e5358#c9ccd0
标题文字--key-color#333#f8fafc
次要文字--muted-color#777#999
边框颜色--main-border-colorrgba(50,50,50,0.06)rgba(255,255,255,0.06)
阴影--main-shadowrgba(116,116,116,0.08)rgba(0,0,0,0.3)

文字色 / 强调

  • 语义文字色: .key-color.focus-color.muted-color.muted-2-color.muted-3-color(依次减弱)。
  • 固定调色(含配套 --this-bg 背景): .c-theme(跟主色)、.c-gray.c-white.c-red / .c-red-2.c-yellow / .c-yellow-2.c-blue / .c-blue-2.c-cyan.c-green / .c-green-2.c-purple / .c-purple-2
  • 渐变字: .cg-theme.cg-red.cg-gray 等(background-clip: text)。
  • 字阶: .px12.em12.em4x.smail.font-bold / .font-normal

背景 / 卡片 / 阴影

  • .main-bgbackground: var(--main-bg-color)
  • .main-shadow — 轻阴影(可与卡片组合)。
  • .box-bg — 主背景 + 阴影(主题盒子)。
  • .zib-widget — 侧栏模块标准卡片:main-bg、内边距 15px、圆角 --main-radius、阴影;附加插件小工具内块可直接套用以统一侧栏。
  • .zib-widget-sm — 小工具无阴影版。
  • .muted-box — 弱灰底圆角块;.muted-box.active 时高亮。
  • .noshadow — 去阴影。
  • .blur-bg — 毛玻璃(backdrop-filter + var(--blur-bg))。
  • .blur-5 / .blur-10 — 元素模糊滤镜。

Flex 与布局

  • 容器:.flex / .inflexinline-flex)。
  • 方向 / 换行:.flex.xx / .inflex.xx(纵向)、.flex.hh(换行)。
  • 对齐:.flex.ac(交叉轴居中)、.flex.ab(底对齐)、.flex.abl(基线)、.flex.at(顶对齐)、.flex.jc(主轴+交叉轴居中)、.flex.jsb(两端)、.flex.jse.flex.jsa
  • 间距:.flex.gap3 / .gap6 / .gap10 / .gap20
  • 子项:.grow1.shrink0.flex0.flex1.flex-auto.flex-auto-h.ellipsis-box(单行截断辅助)。
  • 其它:.container / .widget-container + .relative.block / .inline-block.relative.relative-h(隐藏溢出);.absolute / .fixed(铺满父级,用于遮罩类);.abs-left.abs-right.abs-center(垂直居中锚点)。

间距与圆角

  • 外边距: .mt3 .mt6 .mt10 .mt15 .mt20.mtn6 .mtn10.mb6 .mb10 .mb15 .mb20 .mb30 .mb40.mr3 .mr6 .mr10 .mr20 .mrn10.ml3 .ml6 .ml10 .ml20 .mln3
  • 内边距: .padding-6.padding-h6/.padding-w6.padding-10.padding-h10/.padding-h15.padding-w10/.padding-w15.p-b6.padding-lg
  • 圆角: .radius4.radius8(使用 var(--main-radius))、.radius(大圆角按钮感)。

其它常用

  • .opacity3 / .opacity5 / .opacity8.pointercursor: pointer
  • .border-bottom — 底边线用 var(--main-border-color)
  • .placeholder — 骨架屏占位动画;子类 .img .t1 .k1 等控制尺寸。
  • .obs-animate + .in-view + .ani-slideup 等 — 滚动入场动画。
  • 渐变底(标签/按钮风,用于背景): .jb-red.jb-pink.jb-yellow.jb-blue.jb-green.jb-purple.jb-cyan.jb-vip1.jb-orange 等(与订单类型共用)。
  • 固定调色文字(用于 color 属性): .c-red.c-blue.c-green.c-yellow.c-purple.c-cyan.c-gray.c-white.c-theme

主题内置 SVG 图标

主题 CSF 后台和前台均支持 zibsvg-* 系列 SVG 图标(约 50 个),可作为 CSF 字段 icon 选项或前台 <i> 直接使用:

zibsvg-likezibsvg-viewzibsvg-commentzibsvg-quick-replyzibsvg-timezibsvg-searchzibsvg-moneyzibsvg-rightzibsvg-leftzibsvg-replyzibsvg-circlezibsvg-closezibsvg-minuszibsvg-addzibsvg-check-circlezibsvg-handbagzibsvg-shopping-cartzibsvg-img-listszibsvg-walletzibsvg-giftzibsvg-transitzibsvg-returnzibsvg-add-ringzibsvg-postzibsvg-postszibsvg-huozibsvg-favoritezibsvg-manual-servicezibsvg-menuzibsvg-d-qqzibsvg-d-weibozibsvg-d-wechatzibsvg-d-emailzibsvg-userzibsvg-themezibsvg-signoutzibsvg-setzibsvg-signupzibsvg-user_rpzibsvg-pan_baiduzibsvg-lanzouzibsvg-onedrivezibsvg-tianyizibsvg-menu_2zibsvg-alipayzibsvg-baiduzibsvg-dingtalkzibsvg-xunleizibsvg-123panzibsvg-alipanzibsvg-quarkzibsvg-360yunpanzibsvg-huaweizibsvg-xiaomizibsvg-gitee

前台用法:<i class="zibsvg-like"></i>
CSF 字段 icon:直接填 zibsvg-like 即可。

插件自定义 CSS 时:能用 var(--*) 与上述 class 则不用新写颜色;若必须新增类,命名加插件前缀,避免覆盖 .zib-widget 等主题全局类。

🚀 高级功能

REST API 扩展(可选)

主题在 inc/functions/rest-api/ 下提供了 REST API 端点,插件可扩展:

// 注册自定义 REST API 端点
add_action('rest_api_init', function() {
    register_rest_route('zibll/v1', '/your-endpoint', array(
        'methods'  => 'GET',
        'callback' => 'yourprefix_rest_handler',
        'permission_callback' => function() {
            return current_user_can('read');
        },
    ));
});

function yourprefix_rest_handler($request) {
    // 处理逻辑
    return rest_ensure_response(array('data' => 'value'));
}

注意:REST API 不依赖 zib_require_end,可在插件初始化时直接注册。

主题 REST API 端点清单

主题在 inc/functions/rest-api/ 下注册了以下常用端点:

端点方法用途权限要求
/zibll/v1/user/profileGET获取当前用户资料登录用户
/zibll/v1/user/checkinPOST用户签到登录用户
/zibll/v1/user/balanceGET获取用户余额登录用户
/zibll/v1/posts/listGET获取文章列表公开
/zibll/v1/posts/detailGET获取文章详情公开
/zibll/v1/bbs/postsGET/POST论坛帖子列表/发布登录用户(POST)
/zibll/v1/bbs/categoriesGET论坛分类列表公开
/zibll/v1/shop/productsGET商品列表公开
/zibll/v1/shop/productGET商品详情公开
/zibll/v1/commentsGET/POST评论列表/发布登录用户(POST)

调用示例

// 获取用户资料
fetch('/wp-json/zibll/v1/user/profile')
    .then(res => res.json())
    .then(data => console.log(data));

// 用户签到
fetch('/wp-json/zibll/v1/user/checkin', {
    method: 'POST',
    headers: { 'X-WP-Nonce': _win.nonce }
})
    .then(res => res.json());

主题模板扩展点

页面模板钩子系统

主题使用自定义的模板加载系统,提供以下扩展点:

用户中心页面

// 在用户中心模板加载前执行
add_action('locate_template_user_center', function() {
    // 可在此处进行权限检查或数据准备
});

// 用户中心头部
add_action('user_center_page_header', function() {
    echo '<div class="custom-header">自定义头部</div>';
});

// 用户中心内容区
add_action('user_center_page_content', function() {
    echo '<div class="custom-content">自定义内容</div>';
});

// 用户中心底部
add_action('user_center_page_footer', function() {
    echo '<div class="custom-footer">自定义底部</div>';
});

消息中心页面

add_action('locate_template_msg_center', function() {});
add_action('msg_center_page_header', function() {});
add_action('msg_center_page_content', function() {});
add_action('msg_center_page_footer', function() {});

BBS论坛页面

// 论坛帖子页顶部/底部
add_action('bbs_posts_page_content_top', function() {
    echo '<div class="bbs-custom-top">论坛自定义顶部</div>';
});

add_action('bbs_posts_page_content_bottom', function() {
    echo '<div class="bbs-custom-bottom">论坛自定义底部</div>';
});

// BBS其他页面
add_action('bbs_posts_edit_page_header', function() {});
add_action('bbs_posts_edit_page_content', function() {});

商城商品页

// 商品页内容之后
add_action('shop_product_page_content_after', function() {
    echo '<div class="shop-custom">商品页自定义内容</div>';
});

// 购物车页
add_action('shop_cart_page_content', function() {});

插件开发建议

  • 优先使用 do_action 钩子而非修改模板文件
  • 可通过 locate_template_* 钩子完全替换模板
  • 参考主题 inc/functions/*/page/ 目录下的模板结构
  • 确保钩子优先级合适,避免与其他插件冲突

主题自定义文章类型

主题注册了多个自定义文章类型(Custom Post Type),插件开发时可能需要与之交互:

文章类型标识符用途支持功能
商品product商城商品价格、库存、SKU、分类
论坛帖子bbs_postsBBS帖子分类、精华、置顶
订单order订单记录状态、金额、商品列表
消息message私信消息发送者、接收者、状态
资源resource下载资源下载次数、积分消耗
活动activity活动管理时间、地点、报名

查询示例

// 查询商品列表
$products = new WP_Query(array(
    'post_type' => 'product',
    'post_status' => 'publish',
    'posts_per_page' => 10,
));

// 查询论坛帖子
$posts = new WP_Query(array(
    'post_type' => 'bbs_posts',
    'meta_key' => 'is_essence',
    'meta_value' => 1,
));

主题短代码完整清单

主题提供了6个核心短代码,插件开发时应避免名称冲突:

短代码参数示例用途

评论后可见 指定文章ID 展示单篇文章卡片

分类、数量等 文章列表
李沁:从昆曲闺门旦到演艺界的璀璨之星-小武站
商品ID 商品展示卡片 // 登录可见 // 密码保护 // 积分可见 // VIP可见

插件注册短代码

function yourprefix_shortcode_demo($atts, $content = null)
{
    $atts = shortcode_atts(array(
        'title' => '默认标题',
    ), $atts);

    // 注意:短代码必须 return,不能 echo
    return '<div class="zib-widget"><h4>' . esc_html($atts['title']) . '</h4></div>';
}
add_shortcode('yourprefix_demo', 'yourprefix_shortcode_demo');

插件开发注意

  • 短代码必须在 init 钩子后注册
  • 使用 do_shortcode() 可在PHP中处理短代码
  • 避免与主题短代码名称冲突
  • 所有输出使用 esc_html() / wp_kses_post() 转义
function yourprefix_shortcode_demo($atts, $content = null)
{
    $atts = shortcode_atts(array(
        'title' => '默认标题',
    ), $atts);

    // 注意:短代码必须 return,不能 echo
    return '<div class="zib-widget"><h4>' . esc_html($atts['title']) . '</h4></div>';
}
add_shortcode('yourprefix_demo', 'yourprefix_shortcode_demo');

JavaScript国际化(i18n)系统

主题通过 window._win.i18n 对象提供前端文案翻译,包含200+常用字符串。

访问方式

// main.js 中提供的辅助函数
function zib__(key) {
    var map = window._win && window._win.i18n;
    return map && Object.prototype.hasOwnProperty.call(map, key) ? map[key] : key;
}

// 使用示例
notyf(zib__('processing'), 'load');
console.log(zib__('confirm_delete'));

常用i18n键名

键名中文用途
processing正在处理请稍后…AJAX加载中
please_wait请稍候通用等待提示
done处理完成操作成功
ajax_error操作失败 %1$s %2$sAJAX错误
confirm确认确认对话框
close关闭关闭按钮
loading加载中…加载状态
uploading上传中文件上传
comment_reply回复评论回复
message_all_loaded已加载全部消息加载
countdown_day倒计时
like_thanks已赞!感谢您的支持点赞反馈
search_loading正在搜索,请稍候…搜索状态

插件扩展i18n

// 在插件中添加自定义i18n字符串
add_filter('zib_js_i18n_strings', function($strings) {
    $strings['my_plugin_confirm'] = __('我的插件确认提示', 'my-plugin');
    $strings['my_plugin_success'] = __('操作成功', 'my-plugin');
    $strings['my_plugin_error'] = __('操作失败', 'my-plugin');
    return $strings;
});

注意

  • i18n字符串在页脚通过 wp_json_encode() 输出
  • 支持 JSON_UNESCAPED_UNICODE 确保中文正常显示
  • 插件应使用自己的textdomain避免冲突
  • 完整字符串列表见 inc/functions/zib-js-i18n.php (708行)

主题数据库操作类

主题提供了 zib_db 数据库查询构建器,简化复杂查询:

基本用法

// 简单查询
$db = new zib_db();
$results = $db->table('posts')
    ->where(['post_status' => 'publish'])
    ->limit(10)
    ->get();

// 复杂条件查询
$results = $db->table('posts', 'p')
    ->join('postmeta', 'pm', 'p.ID = pm.post_id')
    ->where([
        'p.post_status' => 'publish',
        'pm.meta_key'   => '_thumbnail_id'
    ])
    ->select('p.ID, p.post_title, pm.meta_value')
    ->orderBy('p.post_date', 'DESC')
    ->limit(10)
    ->get();

// 插入数据
$db->table('custom_table')->insert([
    'name'  => 'test',
    'value' => 123
]);

// 更新数据
$db->table('custom_table')
    ->where(['id' => 1])
    ->update(['value' => 456]);

// 删除数据
$db->table('custom_table')
    ->where(['id' => 1])
    ->delete();

支持的方法

方法说明示例
table($name, $alias)设置表名->table('posts', 'p')
where($conditions)WHERE条件->where(['status' => 1])
whereIn($field, $values)IN查询->whereIn('id', [1,2,3])
whereBetween($field, $range)BETWEEN查询->whereBetween('date', ['2024-01-01', '2024-12-31'])
join($table, $alias, $on)JOIN连接->join('meta', 'm', 'p.id = m.post_id')
select($fields)选择字段->select('id, name, value')
orderBy($field, $dir)排序->orderBy('date', 'DESC')
limit($num)限制数量->limit(10)
offset($num)偏移量->offset(20)
group($field)分组->group('category')
having($condition)HAVING条件->having('COUNT(*) > 5')
distinct()去重->distinct()
get()执行查询$results = $db->get()
insert($data)插入数据->insert(['name' => 'test'])
update($data)更新数据->update(['value' => 123])
delete()删除数据->delete()

聚合查询方法

方法说明示例
count($field)统计数量->count('id')
sum($field)求和->sum('price')
avg($field)平均值->avg('score')
min($field)最小值->min('date')
max($field)最大值->max('date')

聚合查询示例

// 获取用户总数
$total = $db->table('users')->count('ID');

// 计算订单总金额
$revenue = $db->table('orders')
    ->where(['status' => 'completed'])
    ->sum('amount');

// 获取平均评分
$avg_score = $db->table('posts')->avg('rating');

插件开发建议

  • 对于简单查询,仍推荐使用原生 $wpdb
  • 复杂多表JOIN查询可使用 zib_db 构建器
  • 注意表前缀自动处理($wpdb->prefix)
  • 所有输入会自动转义,防止SQL注入
  • 参考 inc/class/db-class.php (1455行)

主题文件操作类

主题提供 ZibFile 类封装常用文件操作:

常用方法

// 检查文件是否存在(区分大小写)
if (ZibFile::file_exists_case($filename)) {
    // 文件存在
}

// 检查路径是否可读/可写
if (ZibFile::path_readable($path)) { }
if (ZibFile::path_writeable($path)) { }

// 获取文件信息
$info = ZibFile::getFileInfo('/path/to/file.jpg');
// 返回: ['name', 'size', 'type', 'mtime', ...]

// 创建目录(递归)
ZibFile::mkdirs('/path/to/new/dir');

// 删除目录(递归)
ZibFile::rmdirs('/path/to/dir');

// 复制文件/目录
ZibFile::copy('/source', '/dest');

// 移动文件/目录
ZibFile::move('/source', '/dest');

// 获取文件扩展名
$ext = ZibFile::getExtension('photo.jpg'); // 返回 'jpg'

// 格式化文件大小
$size = ZibFile::formatSize(1024 * 1024); // 返回 '1 MB'

// 安全写入文件
ZibFile::writeFile('/path/to/file.txt', $content);

// 读取文件内容
$content = ZibFile::readFile('/path/to/file.txt');

插件开发建议

  • 优先使用 ZibFile 而非原生PHP文件函数
  • 自动处理权限检查和错误处理
  • 支持中文文件名和特殊字符
  • 所有路径操作都经过安全检查
  • 参考 inc/class/file-class.php (1588行)

主题工具类

短信验证码类 ZibSMS

支持阿里云、腾讯云、短信宝等多个服务商:

// 发送短信验证码
$result = ZibSMS::send('13800138000', '123456', 'ali');
// 返回: ['error' => 0, 'msg' => '发送成功'] 或 ['error' => 1, 'msg' => '错误信息']

// 验证手机号格式
if (ZibSMS::is_phonenumber('13800138000')) {
    // 格式正确
}

支持的短信服务商

  • ali - 阿里云短信
  • tencent - 腾讯云短信
  • smsbao - 短信宝
  • fcykj - 飞鱼云科技

二维码生成类 QRcode

基于 PHP QR Code 库:

// 生成二维码图片
QRcode::png('https://example.com', $outfile = false, $level = QR_ECLEVEL_L, $size = 4);

// 生成二维码SVG
QRcode::svg('https://example.com', $outfile = false);

// 参数说明:
// - $text: 二维码内容
// - $outfile: 输出文件路径,false则直接输出
// - $level: 纠错级别(L/M/Q/H)
// - $size: 像素大小

邮件发送函数

主题提供统一的邮件发送接口:

// 发送邮件(封装wp_mail)
zib_send_mail($to, $subject, $message, $headers = array());

// 发送HTML邮件
zib_send_html_mail($to, $subject, $html_content);

插件开发建议

  • 短信功能需先在主题后台配置API密钥
  • 二维码生成无需额外依赖
  • 邮件发送遵循WordPress标准,可被SMTP插件拦截
  • 参考 inc/class/sms-class.phpinc/class/qrcode.class.php

主题侧边栏系统

主题提供了极其丰富的侧边栏(Widget Area)注册系统,支持在不同页面位置显示小工具。

主侧边栏区域

主题在 inc/widgets/widget-index.php 中注册了以下主要侧边栏:

全局侧边栏

ID名称说明
all_top_fluid所有页面-顶部全宽度首页、分类页、标签页等顶部
all_bottom_fluid所有页面-底部全宽度首页、分类页、标签页等底部
all_sidebar_top所有页面-侧边栏-顶部侧边栏顶部位置
all_sidebar_bottom所有页面-侧边栏-底部侧边栏底部位置
all_footer底部脚区内部页脚区域内部
mobile_nav_fluid移动端-弹出菜单底部移动端菜单下方

按页面类型划分的侧边栏

支持的页面类型

  • home - 首页
  • single - 文章页
  • cat - 分类页
  • tag - 标签页
  • search - 搜索页
  • author - 作者页
  • user - 用户中心
  • msg - 消息中心

每个页面类型支持的位置

  • top_fluid - 顶部全宽度
  • top_content - 主内容上面
  • bottom_content - 主内容下面
  • bottom_fluid - 底部全宽度
  • sidebar - 侧边栏

示例ID

  • home_top_fluid - 首页顶部全宽度
  • single_sidebar - 文章页侧边栏
  • cat_bottom_content - 分类页主内容下面
  • user_top_content - 用户中心内容区上面

特殊页面侧边栏

// 前台投稿页面
'newposts_sidebar_top'    // 前台投稿-侧边栏顶部
'newposts_sidebar_bottom' // 前台投稿-侧边栏底部

// 动态页面侧边栏(根据页面设置生成)
'page_top_fluid_123'      // [页面:XXX]-顶部全宽度
'page_sidebar_123'        // [页面:XXX]-侧边栏

BBS论坛侧边栏

论坛模块在 inc/functions/bbs/widgets/widgets.php 中注册额外侧边栏:

// 论坛相关侧边栏ID示例
'bbs_plate_sidebar'       // 版块侧边栏
'bbs_posts_sidebar'       // 帖子页侧边栏

商城侧边栏

商城模块在 inc/functions/shop/widgets/widgets.php 中注册:

// 商城相关侧边栏ID示例
'shop_product_sidebar'    // 商品页侧边栏
'shop_cart_sidebar'       // 购物车侧边栏

插件开发建议

1. 使用现有侧边栏

// 在你的插件中,可以直接向已有侧边栏添加小工具
add_action('widgets_init', function() {
    // 注册自定义小工具到特定侧边栏
    register_widget('YourPrefix_Custom_Widget');
});

2.检查侧边栏是否存在

if (is_active_sidebar('home_top_fluid')) {
    dynamic_sidebar('home_top_fluid');
}

3.创建自定义侧边栏

add_action('widgets_init', function() {
    register_sidebar(array(
        'name'          => __('我的插件侧边栏', 'my-plugin'),
        'id'            => 'my_plugin_sidebar',
        'description'   => __('我的插件专用侧边栏', 'my-plugin'),
        'before_widget' => '<div class="zib-widget %2$s">',
        'after_widget'  => '</div>',
        'before_title'  => '<h3>',
        'after_title'   => '</h3>',
    ));
});

4. 注意事项

  • 命名规范: 侧边栏ID使用小写字母和下划线
  • 前缀: 自定义侧边栏建议加插件前缀避免冲突
  • CSS类: 主题自动为widget添加 .zib-widget
  • 预览模式: 主题在自定义预览时会添加编辑按钮
  • fluid区域: ID包含 fluid 的侧边栏会自动包裹在 .fluid-widget-wrap

参考文件

  • inc/widgets/widget-index.php - 主侧边栏注册 (439行)
  • inc/functions/bbs/widgets/widgets.php - BBS侧边栏
  • inc/functions/shop/widgets/widgets.php - 商城侧边栏
  • footer.php - 页脚侧边栏调用示例

主题选项获取函数 _pz()

主题提供统一的选项获取函数 _pz(),用于读取主题后台设置。

基本用法

// 简单获取选项值
$value = _pz('option_name');

// 带默认值
$value = _pz('option_name', 'default_value');

// 获取嵌套数组的子项
$subvalue = _pz('parent_option', false, 'child_key');

参数说明

/**
 * @param string $name     选项的名称
 * @param mixed  $default  如果未找到选项,则返回的默认值
 * @param string $subname  (可选)如果选项是嵌套数组,则为选项的子名称
 * @return mixed           选项的值,如果未找到则返回默认值
 */
function _pz($name, $default = false, $subname = '')

常用选项示例

// 检查功能是否启用
if (_pz('pay_balance_s')) {
    // 余额功能已启用
}

// 获取配置值(带默认值)
$cache_ttl = _pz('cache_time', 3600);

// 获取嵌套配置
$wechat_config = _pz('oauth_weixin', false, 'appid');

性能优化

_pz() 函数内部使用 静态变量缓存,首次调用后会将所有选项缓存在内存中,后续调用直接从缓存读取,无需重复查询数据库:

function _pz($name, $default = false, $subname = '')
{
    static $options = null;
    if ($options === null) {
        $options = get_option('zibll_options'); // 只执行一次
    }
    
    if (isset($options[$name])) {
        if ($subname) {
            return isset($options[$name][$subname]) ? $options[$name][$subname] : $default;
        } else {
            return $options[$name];
        }
    }
    return $default;
}

单独设置选项

如需单独修改某个选项,可使用 _spz() 函数:

// 更新单个选项
_spz('option_name', 'new_value');

插件开发建议

  • 优先使用 _pz() 而非直接 get_option('zibll_options')
  • 利用缓存机制,多次调用无性能损失
  • 始终提供默认值,确保代码健壮性
  • 避免直接修改 $options 数组
  • ⚠️ 注意选项名称,参考主题 inc/options/admin-options.php (660KB)

参考文件

  • inc/dependent.php:112 - _pz() 函数定义
  • inc/dependent.php:131 - _spz() 函数定义
  • inc/options/admin-options.php - 所有可用选项清单

主题缓存系统

主题广泛使用 WordPress Cache API 进行性能优化,插件开发时应遵循相同的缓存策略。

缓存API使用

// 获取缓存
$cache = wp_cache_get($key, $group, $force);

// 设置缓存
wp_cache_set($key, $data, $group, $expire);

// 删除缓存
wp_cache_delete($key, $group);

// 刷新所有缓存
wp_cache_flush();

主题缓存实践

1. 用户头像缓存

// 获取头像(带缓存)
function zib_get_data_avatar($user_id = '', $size = '', $alt = '')
{
    $cache = wp_cache_get($user_id, 'user_avatar', true);
    if (false === $cache) {
        $avatar = zib_get_avatar(null, $user_id, $args);
        wp_cache_set($user_id, $avatar, 'user_avatar');
    } else {
        $avatar = $cache;
    }
    return $avatar;
}

// 更新头像时清除缓存
add_action('user_save_custom_avatar', function ($user_id) {
    wp_cache_delete($user_id, 'user_avatar');
    zib_get_data_avatar($user_id);
}, 10);

2.统计数据缓存

// 获取用户评论数(带缓存)
function get_user_comment_count($user_id, $comments_status = 'approve', $cut = true)
{
    $cache_num = wp_cache_get($user_id, 'user_comment_' . $comments_status . '_count', true);
    
    if (false === $cache_num) {
        $args = array(
            'user_id'   => $user_id,
            'status'    => $comments_status,
            'count'     => true,
            'post_type' => ['post'],
        );
        $count = get_comments($args);
        wp_cache_set($user_id, $count, 'user_comment_' . $comments_status . '_count');
    } else {
        $count = $cache_num;
    }
    
    return $cut ? _cut_count($count) : (int) $count;
}

// 评论状态变化时清除缓存
add_action('transition_comment_status', 'zib_comment_del_cache_status', 10, 3);
add_action('comment_post', 'zib_comment_del_cache', 10);

3.Transient缓存(长期缓存)

// SVG图标精灵缓存(24小时)
function zib_output_svg_sprite() {
    $cache_key = 'zib_svg_sprite_v1';
    $svg_sprite = get_transient($cache_key);
    
    if ($svg_sprite === false) {
        // 生成SVG内容...
        set_transient($cache_key, $svg_sprite, 24 * HOUR_IN_SECONDS);
    }
    
    echo $svg_sprite;
}

插件缓存最佳实践

推荐模式

function myplugin_get_expensive_data($id)
{
    $cache_key = 'myplugin_data_' . $id;
    $cache_group = 'myplugin';
    
    // 尝试从缓存获取
    $data = wp_cache_get($cache_key, $cache_group);
    
    if (false === $data) {
        // 缓存未命中,执行耗时操作
        $data = expensive_database_query($id);
        
        // 存入缓存(有效期1小时)
        wp_cache_set($cache_key, $data, $cache_group, 3600);
    }
    
    return $data;
}

// 数据更新时清除缓存
add_action('myplugin_data_updated', function($id) {
    wp_cache_delete('myplugin_data_' . $id, 'myplugin');
});

主题缓存辅助函数

主题在 func.php 中提供了便捷的缓存函数,封装了 wp_cache_* 系列函数并添加了自动重建机制:

// 获取缓存(带自动重建机制)
zib_cache_get($key, $group, $callback, $expire = 0);

// 设置缓存
zib_cache_set($key, $value, $group, $expire = 0);

// 删除缓存
zib_cache_delete($key, $group);

// 清除整个缓存组
zib_cache_flush_group($group);

使用示例

// 获取或创建缓存(不存在时自动执行回调)
$result = zib_cache_get('my_plugin_data', 'my_plugin', function() {
    return expensive_query();
}, 3600);

// 设置缓存(有效期1小时)
zib_cache_set('my_plugin_result', $data, 'my_plugin', 3600);

// 删除指定缓存
zib_cache_delete('my_plugin_data', 'my_plugin');

// 清除整个缓存组
zib_cache_flush_group('my_plugin');

缓存组建议

缓存组用途过期时间
myplugin插件通用缓存按需设置
user_avatar用户头像永久(更新时清除)
page_url模板页面URL永久
zib_cache_group主题通用缓存按需设置

注意事项

  • 使用有意义的缓存键名,避免冲突
  • 设置合理的过期时间,平衡性能和数据新鲜度
  • 在数据更新时及时清除缓存
  • 使用缓存组隔离不同模块的数据
  • ⚠️ Redis/Object Cache环境下wp_cache_* 函数会使用Redis
  • ⚠️ Transients适合长期缓存,存储在 wp_options 表中

参考文件

  • func.php:725-760 - 主题缓存辅助函数
  • inc/functions/zib-theme.php:579-605 - 头像缓存示例
  • inc/functions/zib-comments-list.php:686-709 - 评论统计缓存
  • inc/functions/bbs/inc/moderator.php:48-91 - BBS版主缓存

Meilisearch 全文搜索引擎

主题集成了 Meilisearch 高性能搜索引擎(需单独部署Meilisearch服务):

基本用法

use Zib\Meilisearch\Client;

// 创建客户端
$client = new Client('http://localhost:7700', 'masterKey');

// 获取索引
$index = $client->index('posts');

// 添加文档
$index->addDocuments([
    ['id' => 1, 'title' => '文章标题', 'content' => '文章内容'],
]);

// 搜索
$results = $index->search('关键词', [
    'limit' => 20,
    'filter' => 'post_status = publish',
]);

// 删除文档
$index->deleteDocument(1);

// 清空索引
$index->deleteAllDocuments();

插件开发注意

  • Meilisearch是外部服务,需在服务器单独部署
  • 适合大型网站替代WordPress默认搜索
  • 需要配置索引同步任务
  • 参考主题 inc/functions/ai/ 目录下的AI搜索集成
  • 参考 inc/class/meilisearch-class.php (383行)

主题更新通知挂钩

插件可通过以下钩子在主题更新/新装时展示自己的运营提示:

// 主题更新时显示插件提示
add_action('zibll_update_notices', function ($version) {
    ?>
    <div class="notice notice-info">
        <p><?php printf(__('你的插件 v%s 已就绪,请查看 %s设置页%s。', 'your-textdomain'),
            YOURPLUGIN_VERSION,
            '<a href="' . admin_url('admin.php?page=yourplugin_options') . '">',
            '</a>'
        ); ?></p>
    </div>
    <?php
});

// 主题新安装时显示
add_action('zibll_new_install_notices', function ($version) {
    // 同上格式
});

主题升级任务机制

主题 inc/options/upgrade.php 内有 zib_update_theme_tasks_X_Y() 系列(X.Y 为目标版本号),在新版安装/升级时自动调用。插件可参考此机制做自己的版本迁移:

// 在插件激活或特定版本时执行升级任务
function yourprefix_upgrade_to_1_1()
{
    // 数据迁移、建表等
}
register_activation_hook(__FILE__, function () {
    $version = get_option('yourprefix_version', '0.0.0');
    if (version_compare($version, '1.1.0', '<')) {
        yourprefix_upgrade_to_1_1();
        update_option('yourprefix_version', '1.1.0');
    }
});

钩子与调试习惯

  • 主题专有能力与扩展点见上文 「主题 PHP API 速查」;以下为通用习惯。
  • 善用 do_actionapply_filtersadd_actionadd_filter;主题与 WordPress 核心钩子均可结合使用。
  • 改写页面展示不必仅限 PHP,可按需配合前端 JS。
  • 注意钩子优先级与性能:重逻辑加 is_admin()wp_doing_ajax() 等守卫。
  • 全局搜索主题内 do_action / apply_filters 找扩展点。

进阶优化建议

🛠️ 最佳实践与优化

1. CSF 字段类型兼容性白名单

根据实际插件开发经验,并非所有 CSF 字段类型在子比主题环境中都稳定可用。建议优先使用以下经过验证的字段类型:

字段类型推荐使用注意事项
text基础文本输入,兼容性最佳
textarea多行文本输入
select下拉选择框
radio单选按钮组
checkbox复选框(推荐替代 switcher)
number数字输入框
color颜色选择器
upload文件上传
icon图标选择器
switcher开关控件,主题内大量使用且稳定
button_set按钮组选择,主题广泛用于后台设置
spinner数字步进器,带单位显示
submessage提示信息块,用于分组说明
notice通知提示框,支持 success/warning/danger/info
repeater重复字段组,适合列表型配置
group字段组,可折叠
accordion手风琴折叠面板
background背景设置(颜色+图片)
icon图标选择器(支持 Font Awesome + zibsvg)
gallery图库选择
palette调色板
code_editor代码编辑器(CodeMirror)
image_select⚠️图片选择,需确保图片 URL 有效

使用示例(推荐方式):

// 使用 switcher(主题内广泛使用,稳定可靠)
array(
    'id'      => 'enabled',
    'type'    => 'switcher',
    'title'   => __('启用功能', 'your-textdomain'),
    'default' => true,
),

// 或使用 checkbox(兼容性最佳)
array(
    'id'      => 'enabled_alt',
    'type'    => 'checkbox',
    'title'   => __('启用功能(备选)', 'your-textdomain'),
    'default' => '1', // 字符串 '1'/'0' 而非布尔值
),

2. AJAX 安全标准增强

参考 zibll-user 等插件的实际实现,AJAX 处理器应包含完整的安全校验:

function yourprefix_ajax_handler() {
    // 1. 权限检查(优先)
    if (!current_user_can('edit_posts')) {
        wp_send_json_error(array('msg' => '权限不足'), 403);
    }

    // 2. Nonce 验证
    check_ajax_referer('yourprefix_nonce', 'nonce');

    // 3. 参数验证
    if (!isset($_POST['data']) || empty($_POST['data'])) {
        wp_send_json_error(array('msg' => '参数错误'), 400);
    }

    // 4. 参数清理
    $data = sanitize_text_field(wp_unslash($_POST['data']));

    // 5. 业务逻辑
    try {
        $result = yourprefix_process_data($data);
        wp_send_json_success(array('result' => $result));
    } catch (Exception $e) {
        wp_send_json_error(array('msg' => '处理失败'), 500);
    }
}

// 注册钩子(仅登录用户访问)
add_action('wp_ajax_yourprefix_action', 'yourprefix_ajax_handler');
// add_action('wp_ajax_nopriv_yourprefix_action', 'yourprefix_ajax_handler'); // 公开接口取消注释

3. 主题函数兼容性封装

ZibPay 核心函数清单

函数文件用途
zibpay_get_user_balance($user_id)zibpay-balance.php获取用户余额
zibpay_update_user_balance($user_id, $data)zibpay-balance.php更新用户余额(推荐)
zibpay_get_user_points($user_id)zibpay-points.php获取用户积分
zibpay_update_user_points($user_id, $data)zibpay-points.php更新用户积分
zibpay_is_paid($post_id, $user_id)zibpay-ajax.php检查是否已购买
zibpay_get_post_paid_data_by_user($post_id, $user_id)zibpay-ajax.php获取付费详情

更新余额/积分的数据格式:

$data = array(
    'value' => 100,           // 变动值(正数增加,负数减少)
    'type'  => 'manual_add',  // 变动类型标识
    'desc'  => '手动增加余额', // 变动描述
);
zibpay_update_user_balance($user_id, $data);

⚠️ 重要:切勿直接操作 user_meta 中的 balancepoints,必须通过上述函数以保证日志记录和事务一致性。

对于余额、积分等主题核心功能,必须使用 function_exists 做兼容性检查:

/**
 * 获取用户余额(带兼容性封装)
 */
function yourprefix_get_user_balance($user_id) {
    if (function_exists('zibpay_get_user_balance')) {
        return zibpay_get_user_balance($user_id);
    }
    // Fallback:直接读取 meta(不推荐,仅作最后兜底)
    $balance = get_user_meta($user_id, 'balance', true);
    return floatval($balance);
}

/**
 * 更新用户余额(必须走主题统一接口)
 */
function yourprefix_update_user_balance($user_id, $amount, $type = 'add', $desc = '') {
    if (!function_exists('zibpay_update_user_balance')) {
        yourprefix_log_error('zibpay_update_user_balance 函数不存在');
        return false;
    }

    $data = array(
        'value' => $type === 'add' ? $amount : -$amount,
        'type'  => $desc,
        'desc'  => $desc,
    );

    return zibpay_update_user_balance($user_id, $data);
}

4. CSF 菜单结构规范

创建多级菜单时,parent 必须使用 section id 而非显示标题:

// 正确:使用 section id 作为 parent
CSF::createSection($options_key, array(
    'id'     => 'parent_section',
    'title'  => '父级设置',
    'icon'   => 'fa fa-folder',
    // 父 section 不包含 fields,仅作为容器
));

CSF::createSection($options_key, array(
    'id'     => 'child_section',
    'title'  => '子级设置',
    'parent' => 'parent_section', // 使用 id,不是 '父级设置'
    'fields' => array(
        // 字段定义
    ),
));

5. 调试工具与错误处理

WordPress 调试配置

wp-config.php 中启用调试:

// 启用调试模式
define('WP_DEBUG', true);

// 记录错误到日志文件
define('WP_DEBUG_LOG', true);  // 日志位置:wp-content/debug.log

// 不在页面显示错误(生产环境建议 false)
define('WP_DEBUG_DISPLAY', false);

// 保存数据库查询(性能调试)
define('SAVEQUERIES', true);

主题特定调试:

  • 主题错误日志:wp-content/debug.log
  • zibll 广告调试:wp-content/zibll-ad-debug.log
  • 临时文件目录:wp-content/zib-temp/

添加统一的日志记录和调试函数:

/**
 * 记录错误日志
 */
function yourprefix_log_error($message, $data = array()) {
    if (WP_DEBUG) {
        $log_data = !empty($data) ? ' | Data: ' . print_r($data, true) : '';
        error_log('[YourPlugin] ' . $message . $log_data);
    }
}

/**
 * 调试输出(仅开发环境)
 */
function yourprefix_debug($data, $label = '') {
    if (!WP_DEBUG || !is_admin()) return;
    
    $label = $label ? "<strong>$label:</strong><br>" : '';
    echo "<pre style='background:#fff; padding:10px; border:1px solid #ccc; margin:10px;'>";
    echo $label;
    var_dump($data);
    echo "</pre>";
}

/**
 * 安全的选项读取(带默认值)
 */
function yourprefix_get_option($key, $default = false) {
    static $options = null;
    
    // 开发环境不缓存,便于调试
    if (WP_DEBUG) {
        $options = get_option('yourplugin_options');
        return isset($options[$key]) ? $options[$key] : $default;
    }
    
    if ($options === null) {
        $options = get_option('yourplugin_options');
    }
    return isset($options[$key]) ? $options[$key] : $default;
}

6. 性能优化:缓存机制

参考主题 _pz() 函数的静态缓存模式,并结合 WP 缓存 API:

/**
 * 获取选项(带多层缓存)
 */
function yourprefix_get_option($key, $default = false) {
    $cache_key = 'yourplugin_option_' . $key;
    
    // 尝试从 WP 缓存获取
    if (function_exists('wp_cache_get')) {
        $cached = wp_cache_get($cache_key, 'yourplugin');
        if ($cached !== false) {
            return $cached;
        }
    }
    
    // 静态缓存作为备选
    static $options = null;
    if ($options === null) {
        $options = get_option('yourplugin_options', array());
    }
    
    $value = isset($options[$key]) ? $options[$key] : $default;
    
    // 设置 WP 缓存(有效期5分钟)
    if (function_exists('wp_cache_set')) {
        wp_cache_set($cache_key, $value, 'yourplugin', 300);
    }
    
    return $value;
}

/**
 * 更新选项(同时清理缓存)
 */
function yourprefix_update_option($key, $value) {
    $options = get_option('yourplugin_options', array());
    $options[$key] = $value;
    update_option('yourplugin_options', $options);
    
    // 清理相关缓存
    if (function_exists('wp_cache_delete')) {
        wp_cache_delete('yourplugin_option_' . $key, 'yourplugin');
        wp_cache_delete('yourplugin_options', 'yourplugin');
    }
}

7. 数据库查询优化

参考主题查询优化策略,使用高效的 WP_Query 参数:

/**
 * 获取帖子列表(优化版)
 */
function yourprefix_get_posts($args = array()) {
    $defaults = array(
        'post_type'              => 'post',
        'post_status'            => 'publish',
        'posts_per_page'         => 10,
        'no_found_rows'          => true,           // 不需要总条数时设置为true
        'update_post_term_cache' => false,         // 不需要分类缓存时关闭
        'update_post_meta_cache' => false,         // 不需要meta缓存时关闭
        'ignore_sticky_posts'    => true,
        'fields'                 => 'ids',         // 只需要ID时使用
    );
    
    $args = wp_parse_args($args, $defaults);
    $query = new WP_Query($args);
    
    return $query->posts;
}

8. 安全增强:输出转义规范

参考主题的转义实践,确保所有输出都经过正确转义:

场景推荐函数示例
HTML内容esc_html()echo esc_html($text);
HTML属性esc_attr()<div class="<?php echo esc_attr($class); ?>">
URLesc_url()<a href="<?php echo esc_url($url); ?>">
JavaScriptesc_js()var data = '<?php echo esc_js($data); ?>';
富文本内容wp_kses_post()echo wp_kses_post($content);
SQL查询esc_sql()$search = esc_sql($search);

完整示例:

function yourprefix_render_post($post) {
    if (!is_object($post)) return;
    
    ?>
    <article id="post-<?php echo esc_attr($post->ID); ?>" class="post-card">
        <h2><a href="<?php echo esc_url(get_permalink($post->ID)); ?>">
            <?php echo esc_html(get_the_title($post->ID)); ?>
        </a></h2>
        <div class="post-content">
            <?php echo wp_kses_post(get_the_content($post->ID)); ?>
        </div>
        <script>
            var postData = {
                id: <?php echo absint($post->ID); ?>,
                title: '<?php echo esc_js(get_the_title($post->ID)); ?>'
            };
        </script>
    </article>
    <?php
}

9. 权限检查最佳实践

主题统一权限判断函数

主题提供了统一的权限判断入口 zib_current_user_can(),支持多种能力类型:

/**
 * 检查当前用户是否具有指定能力
 * 
 * @param string $capability 能力名称
 * @param mixed ...$args 额外参数(某些能力需要)
 * @return bool
 */
function zib_current_user_can($capability, ...$args)

// 常用能力示例:
if (zib_current_user_can('new_post_add')) { /* 能否发布文章 */ }
if (zib_current_user_can('comment_view', $post)) { /* 能否查看评论 */ }
if (zib_current_user_can('view_order', $order)) { /* 能否查看订单 */ }
if (zib_current_user_can('order_close', $order)) { /* 能否关闭订单 */ }

能力配置位置:主题后台 → 用户中心 → 权限设置,可自定义各角色对应的能力。

常用能力清单

能力名称用途需要对象参数
new_post_add能否发布文章
new_post_edit能否编辑文章是($post)
new_post_delete能否删除文章是($post)
comment_view能否查看评论是($post)
comment_edit能否编辑评论是($comment)
comment_delete能否删除评论是($comment)
view_order能否查看订单是($order)
order_close能否关闭订单是($order)
shop_product_add能否添加商品
shop_product_edit能否编辑商品是($product)
bbs_posts_add能否发布论坛帖子
bbs_posts_edit能否编辑论坛帖子是($post)
bbs_posts_essence能否设精华帖是($post)
bbs_posts_topping能否置顶帖子是($post)
user_ban能否封禁用户是($user)
user_auth能否审核认证

插件开发建议

  • 优先使用 zib_current_user_can() 而非原生 current_user_can(),因为它集成了主题的 VIP、等级、认证等扩展判断
  • 对于主题特有的能力(如商城、论坛相关),必须使用此函数
  • 通用 WordPress 能力(如 edit_posts)仍可使用原生函数

参考主题 zib_current_user_can() 的封装模式:

/**
 * 检查用户权限(带日志记录)
 */
function yourprefix_current_user_can($capability, $object = null) {
    // 管理员拥有所有权限
    if (current_user_can('administrator')) {
        return true;
    }
    
    // 检查标准权限
    if (current_user_can($capability)) {
        return true;
    }
    
    // 对象级权限检查(如订单、帖子等)
    if ($object && is_object($object)) {
        // 检查对象所有者
        if (isset($object->user_id) && $object->user_id == get_current_user_id()) {
            return true;
        }
    }
    
    yourprefix_log_error('权限检查失败', array(
        'capability' => $capability,
        'user_id' => get_current_user_id()
    ));
    
    return false;
}

/**
 * AJAX权限检查快捷函数
 */
function yourprefix_check_ajax_permission($capability = 'edit_posts') {
    if (!is_user_logged_in()) {
        wp_send_json_error(array('msg' => '请先登录'), 401);
    }
    
    if (!current_user_can($capability)) {
        wp_send_json_error(array('msg' => '权限不足'), 403);
    }
}

8. 代码组织与架构优化

参考主题的模块化架构,建议的插件目录结构:

your-plugin/
├── your-plugin.php              # 入口文件(依赖检测 + 自动加载)
├── inc/
│   ├── core/
│   │   ├── bootstrap.php        # 初始化与依赖检测
│   │   ├── hooks.php            # 钩子注册中心
│   │   └── autoloader.php       # 自动加载器
│   ├── admin/
│   │   ├── options.php          # CSF 后台选项
│   │   ├── menus.php            # 后台菜单注册
│   │   └── notices.php          # 后台通知
│   ├── frontend/
│   │   ├── shortcodes.php       # 短代码注册
│   │   ├── widgets.php          # 小工具
│   │   └── templates.php        # 模板函数
│   ├── ajax/
│   │   ├── handlers.php         # AJAX 处理器
│   │   └── endpoints.php        # REST API 端点
│   └── utils/
│       ├── validators.php       # 验证工具
│       ├── sanitizers.php       # 清理工具
│       └── helpers.php          # 辅助函数
├── assets/
│   ├── css/
│   │   ├── frontend.css         # 前台样式
│   │   └── admin.css            # 后台样式
│   ├── js/
│   │   ├── frontend.js          # 前台脚本
│   │   └── admin.js             # 后台脚本
│   └── images/                  # 图片资源
├── languages/                   # 语言包
│   └── your-plugin-zh_CN.mo/po
├── templates/                   # 模板文件(可选)
└── README.md                    # 说明文档

✅ 自检清单

在发布插件前,请确保完成以下检查:

  • [ ] 主题依赖:主题非 zibll 时已 return 且不调用主题 API
  • [ ] CSF 钩子:CSF / CSF_Widget 仅出现在 zib_require_end 回调内
  • [ ] 命名唯一性options_key、widget key、函数前缀全局唯一
  • [ ] 小工具一致性:小工具输出函数名与 CSF::createWidget 第一个参数一致
  • [ ] 安全转义:对外输出已转义,权限与 nonce 按业务补齐
  • [ ] AJAX 安全:接口已注册 nonce 验证 + 权限检查;公开接口同时注册 nopriv 钩子
  • [ ] JS 异步加载:前台 JS 使用 _win / zib_ajax / notyf 前已处理异步加载或存在性判断
  • [ ] CSS 复用:插件前台 HTML 优先使用 main.css 工具类与 CSS 变量,避免与主题视觉脱节
  • [ ] CSS 命名空间:插件自定义 CSS 类名带插件前缀,不覆盖主题全局类(.zib-widget 等)
  • [ ] 暗色模式适配:使用 var(--*) 变量引用,不硬编码 #fff / #333 等色值
  • [ ] jQuery 依赖:声明正确,不假设 WP 默认 jQuery 路径
  • [ ] CSS 加载顺序:依赖 main 确保在主题样式之后
  • [ ] 版本管理:插件版本号、介绍、更新日志同步更新
  • [ ] 函数存在性检查:使用 function_exists 检查主题函数后再调用
  • [ ] ZibPay 统一接口:余额/积分变更走主题统一更新接口(如 zibpay_update_user_balance

📖 参考资源

核心文件路径

类型路径说明
CSF 框架(活跃)inc/csf-framework/当前使用的 CSF 版本
CSF 框架(旧版)inc/codestar-framework/旧版兼容
CSF 选项示例inc/options/admin-options.php660KB,完整字段示例
CSF Widget 类inc/csf-framework/classes/widget-options.class.phpWidget 基类
Zib_CFSwidgetinc/widgets/widget-class.php兼容壳
小工具示例inc/widgets/widget-more.php参考实现
主题加载结束inc/inc.php:126do_action('zib_require_end')
_win 注入inc/functions/zib-footer.php:65-110全局 JS 对象
前台脚本注册inc/functions/zib-theme.php:1044-1093_load_scripts / _jsloader / _cssloader
主题主逻辑js/main.jsjs/loader.js 配合
前台全局样式css/main.css14736 行,线上为 main.min.css
主题选项实现inc/dependent.php_pz / _spz 函数定义
主题选项注册inc/options/options.php选项配置入口
主题升级任务inc/options/upgrade.php版本迁移逻辑
用户系统inc/functions/user/用户相关功能
UI 组件函数inc/functions/functions.php通用 UI 函数
ZibPay 函数zibpay/functions/付费系统核心

在线资源

© 版权声明
THE END
喜欢就支持一下吧
点赞5232支持作者 分享
评论标题 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容