子比主题开发文档
使用指南Codestar Framework主题扩展在线部署AI 功能推荐插件赞助打赏

后台设置菜单

按子比主题源码拆解 CSF 后台设置页、section 分层、字段保存、性能优化和读取方式。

入口文件

子比主题的全站设置页由 inc/options/admin-options.php 注册,入口函数是:

function zib_csf_admin_options()

它不会在 functions.php 里直接写字段。主题启动链路是:

functions.php
inc/inc.php
inc/options/options.php
inc/options/admin-options.php

inc/options/options.php 只负责加载后台设置相关文件,并启用子比需要的图标版本:

zib_require(array(
    'inc/options/options-module',
    'inc/options/upgrade',
));

if (is_admin()) {
    zib_require(array(
        'admin-options',
        'metabox-options',
        'profile-options',
        'action',
    ), false, 'inc/options/');
}

add_filter('csf_fa4', '__return_true');

因此读后台设置页时,不要只看一个 CSF::createOptions()。要把 options.phpadmin-options.phpoptions-module.phpdependent.php 一起看。

Prefix 与菜单

主题后台设置的唯一前缀是:

$prefix = 'zibll_options';

设置页创建代码在 zib_csf_admin_options() 前半段:

CSF::createOptions($prefix, array(
    'menu_title'         => __('zibll主题设置', 'zib_language'),
    'menu_slug'          => 'zibll_options',
    'framework_title'    => __('子比主题', 'zib_language'),
    'show_in_customizer' => false,
    'save_defaults'      => !$no_create,
    'footer_text'        => sprintf(__('更优雅的wordpress主题-Zibll主题 V%s', 'zib_language'), wp_get_theme()['Version']),
    'footer_credit'      => '<i class="fa fa-fw fa-heart-o" aria-hidden="true"></i> ',
    'theme'              => 'light',
));

这里有三个必须记住的点:

配置子比写法影响
$prefixzibll_options最终保存到 wp_options.option_name = zibll_options
menu_slugzibll_options后台访问地址和 Ajax 保存都围绕这个 slug
save_defaults!$no_create非设置页不强行创建大量默认值

主题设置不要用 get_option('zibll_options') 到处散读,前台统一走 _pz()

一级分组

子比主题先注册一级 section,让左侧菜单形成业务域:

CSF::createSection($prefix, array(
    'id'    => 'basic',
    'title' => __('全局&功能', 'zib_language'),
    'icon'  => 'fa fa-fw fa-bullseye',
));

CSF::createSection($prefix, array(
    'id'    => 'page',
    'title' => __('页面&显示', 'zib_language'),
    'icon'  => 'fa fa-fw fa-calendar-check-o',
));

CSF::createSection($prefix, array(
    'id'    => 'post',
    'title' => __('文章&列表', 'zib_language'),
    'icon'  => 'fa fa-fw fa-map-o',
));

CSF::createSection($prefix, array(
    'id'    => 'user',
    'title' => __('用户&互动', 'zib_language'),
    'icon'  => 'fa fa-fw fa-user-o',
));

CSF::createSection($prefix, array(
    'id'    => 'pay',
    'title' => __('支付&付费', 'zib_language'),
    'icon'  => 'fa fa-fw fa-jpy',
));

源码里还包括 capshopforumover 等一级分组。一级 section 通常只做目录,不放字段。真正的配置放在带 parent 的子 section 中。

子 Section

子 section 用 parent 绑定到一级分组。比如 LOGO 图像属于 basic

CSF::createSection($prefix, array(
    'parent'      => 'basic',
    'title'       => __('LOGO图像', 'zib_language'),
    'icon'        => 'fa fa-fw fa-image',
    'description' => '',
    'fields'      => array(
        array(
            'id'      => 'logo',
            'type'    => 'upload',
            'title'   => __('LOGO', 'zib_language'),
            'library' => 'image',
            'preview' => true,
        ),
    ),
));

子比设置页的组织习惯是:

一级分组典型子 section
basicLOGO 图像、SEO 优化、常用功能、显示布局、搜索功能、Email 邮件、自定义代码
page顶部导航栏、顶部多功能组件、底部页脚、首页配置、分类页面、标签页面、用户主页
post文章列表、列表缩略图、文章页面、高级筛选、文章功能、评论设置、前台投稿
user注册登录、第三方登录、消息通知、禁封举报、身份认证、用户徽章、用户等级、签到奖励
pay知识付费、余额充值、VIP 会员、创作分成、推广返佣、收款接口
forum社区论坛相关开关、版块、话题、权限和展示配置
over系统工具、网站安全、IP 归属地、API 内容审核、文档模式

这个分层就是文档分类和后台配置设计的参考:先按业务域分,再按页面或功能切分。

字段结构

字段统一写在 fields 数组里。子比保留 Codestar 的字段格式,同时大量使用 CFS_Module 生成复合字段:

array(
    'id'      => 'theme_mode',
    'type'    => 'radio',
    'title'   => __('主题模式', 'zib_language'),
    'inline'  => true,
    'default' => 'white',
    'options' => array(
        'white' => __('亮色模式', 'zib_language'),
        'dark'  => __('深色模式', 'zib_language'),
    ),
)

常见字段属性:

属性用途
id保存到 zibll_options 的键名
type字段类型,例如 switchertextuploadgroup
title后台字段标题
subtitle标题下方补充说明
desc字段底部说明
default默认值
options选择项、调色板、分组子字段等
dependency控制字段显示隐藏
sanitize是否让 CSF 清洗字段值

子比源码里字段数量很大,不建议复制整段。读法是先找 section 标题,再看字段 id,最后用 _pz('字段id') 搜索前台读取位置。

读取设置

_pz()inc/dependent.php 中定义:

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;
}

读取普通字段:

$post_article_s = _pz('post_article_s');
$ajax_trigger   = _pz('ajax_trigger', __('加载更多', 'zib_language'));

读取数组子字段:

$class = _pz('checkin_header_user_option', 'c-yellow', 'class');
$text  = _pz('checkin_header_user_option', __('签到领取今日奖励', 'zib_language'), 'text');

读取列表字段:

$buttons = _pz('translate_buttons', array());
foreach ($buttons as $button) {
    $language = !empty($button['language']) ? $button['language'] : '';
}

写入设置

主题提供 _spz() 单独更新某个设置键:

function _spz($name, $value)
{
    $get_option        = get_option('zibll_options');
    $get_option        = is_array($get_option) ? $get_option : array();
    $get_option[$name] = $value;
    return update_option('zibll_options', $get_option);
}

后台设置页里的大部分字段由 CSF 保存。业务代码需要主动修改主题设置时再用 _spz(),不要整包覆盖 zibll_options,否则容易丢掉其他字段。

$no_create 性能判断

admin-options.php 体量很大,所以主题用 $no_create 判断当前请求是否真的需要完整创建字段。核心思路是:

$no_create = (
    (wp_doing_ajax() && (empty($_POST['action']) || !strstr($_POST['action'], 'csf_' . $prefix)))
    ||
    (!wp_doing_ajax() && (empty($_GET['page']) || $_GET['page'] !== $prefix))
);

作用:

  • zibll_options 设置页,不创建全部默认值。
  • 非当前 CSF Ajax 保存请求,不执行大量字段保存逻辑。
  • 后台其它页面加载更轻。

如果你在主题内新增大量设置,也要沿用这个思路。小字段可以直接写,大型字段组要避免每个后台页面都初始化。

保存 Hook

子比改写过 inc/csf-framework/classes/admin-options.class.php,保存流程里有可用 Hook:

do_action("csf_{$unique}_save_before", $request, $this);
do_action("csf_{$unique}_save_after", $request, $this);

zibll_options 来说就是:

add_action('csf_zibll_options_save_before', 'zib_before_save_options', 10, 2);
add_action('csf_zibll_options_save_after', 'zib_after_save_options', 10, 2);

适合处理缓存刷新、衍生数据更新、外部资源同步。不要在这里输出 HTML,Ajax 保存会直接受到影响。

HTML 保存

子比对原版 CSF 的保存行为做过调整,部分字段允许保存 HTML。结果是更灵活,但也要求读取和输出时自己判断上下文:

$html = _pz('footer_html');
echo wp_kses_post($html);

普通文本:

echo esc_html(_pz('custom_text'));

URL:

echo esc_url(_pz('custom_url'));

属性:

echo esc_attr(_pz('custom_class'));

排查路径

后台设置相关问题按这个顺序查:

  1. inc/options/options.php 是否在后台加载了 admin-options.php
  2. class_exists('CSF') 是否为 true。
  3. $prefixmenu_slug、访问地址是否都是 zibll_options
  4. 字段是否在 fields 数组中,id 是否唯一。
  5. 保存后 wp_options.zibll_options 中是否有对应键。
  6. 前台是否用 _pz() 读取,而不是读错 option。
  7. 如果是 Ajax 保存失败,看 admin-ajax.php 返回值和 PHP 错误日志。

On this page