搜索全站
主题 16 分钟阅读

Customizer API 添加主题设置项:Panel/Section/Setting/Control 写法

客户要改底部版权、主色调,难道每次都得动代码?用 Customizer API 把设置做成后台可视化面板,本文拆解 Panel/Section/Setting/Control 四层结构、数据存放位置、sanitize 回调与实时预览写法。

U
UFO_PF 2025-07-30 · 阅读 16 分钟
Cu 主题
阅读提示
本文约 6,152 字,预计阅读 16 分钟。文中命令与配置均经过实测,可直接参考执行。

引言:改一个版权文字就要动 FTP 的日子

做主题交付时最常被问到的两个问题:「底部这行版权怎么改?」「主色能不能换成我们的品牌蓝?」如果这些值写死在 footer.php 和 style.css 里,客户每次调整都要找你,或者自己进 FTP 改文件——改错了整站白屏,最后还是你的锅。

WordPress 自带的「自定义」(Customizer)就是为了解决这件事:左侧面板填值,右侧实时预览,点「发布」即刻生效,不需要代码。很多主题作者却直接上第三方框架(Kirki、Redux、Codestar),其实原生 Customizer API 一套 Panel / Section / Setting / Control 就够用,代码不到一百行,且不引入任何额外依赖。真正需要复杂控件(repeater、typography、sortable)时才考虑框架,那是另一篇文章要谈的事。

原理分析:四个对象各自负责什么

Customizer 的所有东西都由 WP_Customize_Manager 这个管理器对象持有,我们通过 customize_register 钩子拿到它:

对象 作用 常见坑
Panel 顶层分组容器,可折叠 没有 Panel 也能直接用 Section,不必强行套一层
Section 面板内的小分组 id 冲突会覆盖,务必加主题前缀
Setting 真正存数据的地方 默认存 theme_mod,改 type 才存 option
Control 数据对应的 UI 控件 没有 Control 的 Setting 存在但不可见

关键点有三个。第一,Setting 与 Control 是一一对应关系:Control 的 settings 指向 Setting 的 id,只写 Control 不写 Setting,界面上输入框能出来但值存不进去。第二,数据默认是 theme_mod,每个主题独立存放,切换主题后设置丢失;传 type => 'option' 则存进 wp_options 表,换主题还在,但不支持「主题切换后预览」的暂存机制。第三,sanitize_callback 是安全底线,Customizer 保存时会调用它,返回值才是最终入库的值——不写这个函数,等于把用户输入原样写进数据库。

刷新方式由 transport 决定:refresh(默认,整页 iframe 刷新)和 postMessage(JS 局部替换,无刷新)。视觉类设置(颜色、字号)适合 postMessage,结构性设置(是否显示侧边栏)用 refresh 更稳。

保姆级实操

第一步:挂载 customize_register,建 Panel 与 Section

add_action( 'customize_register', 'mimangfei_customize_register' );

function mimangfei_customize_register( $wp_customize ) {

    $wp_customize->add_panel( 'mimangfei_options', array(
        'title'       => __( '主题设置', 'mimangfei' ),
        'description' => __( 'Logo、配色与页脚设置', 'mimangfei' ),
        'priority'    => 160,
    ) );

    $wp_customize->add_section( 'mimangfei_footer', array(
        'title'    => __( '页脚', 'mimangfei' ),
        'panel'    => 'mimangfei_options',
        'priority' => 20,
    ) );

    $wp_customize->add_section( 'mimangfei_colors', array(
        'title'    => __( '配色', 'mimangfei' ),
        'panel'    => 'mimangfei_options',
        'priority' => 10,
    ) );
}

priority 决定排序,核心自带的「站点身份」是 20、「颜色」是 40,一般用 160 把自定义面板排到后面。

第二步:注册 Setting,写好默认值与 sanitize

$wp_customize->add_setting( 'mimangfei_footer_text', array(
    'default'           => __( '© 2026 迷忙飞工作室', 'mimangfei' ),
    'transport'         => 'postMessage',
    'sanitize_callback' => 'sanitize_text_field',
) );

$wp_customize->add_setting( 'mimangfei_accent_color', array(
    'default'           => '#2563eb',
    'transport'         => 'postMessage',
    'sanitize_callback' => 'sanitize_hex_color',
) );

$wp_customize->add_setting( 'mimangfei_show_search', array(
    'default'           => true,
    'sanitize_callback' => 'mimangfei_sanitize_checkbox',
) );

function mimangfei_sanitize_checkbox( $value ) {
    return (bool) $value;
}

内置 sanitize 函数可直接复用:sanitize_text_field、sanitize_hex_color、esc_url_raw、absint、wp_filter_nohtml_kses。自定义回调则写在同一个文件里。

第三步:加 Control,普通控件与特殊控件

$wp_customize->add_control( 'mimangfei_footer_text', array(
    'label'   => __( '页脚版权文字', 'mimangfei' ),
    'section' => 'mimangfei_footer',
    'type'    => 'text',
) );

$wp_customize->add_control( new WP_Customize_Color_Control(
    $wp_customize,
    'mimangfei_accent_color',
    array(
        'label'   => __( '主色调', 'mimangfei' ),
        'section' => 'mimangfei_colors',
    )
) );

$wp_customize->add_control( 'mimangfei_show_search', array(
    'label'   => __( '顶部显示搜索框', 'mimangfei' ),
    'section' => 'mimangfei_footer',
    'type'    => 'checkbox',
) );

文本类控件可以直接用 add_control( $id, $args ) 简写(id 与 Setting 同名);颜色、图片这类需要实例化控件类:WP_Customize_Color_Control、WP_Customize_Image_Control、WP_Customize_Cropped_Image_Control(可指定裁切宽高)、WP_Customize_Upload_Control。下拉框用 type => 'select' 加 'choices' 数组,radio 同理。

第四步:在模板里输出

$footer_text = get_theme_mod( 'mimangfei_footer_text', __( '© 2026 迷忙飞工作室', 'mimangfei' ) );
echo '<p class="site-footer__text">' . esc_html( $footer_text ) . '</p>';

get_theme_mod( $name, $default ) 的第二个参数是兜底值,未保存过时用它。输出一律再过一次 esc_html() / esc_attr() / esc_url()——sanitize 管入库,escaping 管输出,两件事不能互相替代。

第五步:主色调注入内联 CSS

add_action( 'wp_head', 'mimangfei_customizer_css' );

function mimangfei_customizer_css() {
    $accent = get_theme_mod( 'mimangfei_accent_color', '#2563eb' );
    ?>
    <style>
    :root { --mf-accent: <?php echo esc_attr( $accent ); ?>; }
    a, .site-title a { color: var(--mf-accent); }
    .button, button, input[type="submit"] { background: var(--mf-accent); }
    </style>
    <?php
}

第六步:postMessage 实时预览

wp.customize( 'mimangfei_footer_text', function( value ) {
    value.bind( function( newval ) {
        $( '.site-footer__text' ).text( newval );
    } );
} );

wp.customize( 'mimangfei_accent_color', function( value ) {
    value.bind( function( newval ) {
        document.documentElement.style.setProperty( '--mf-accent', newval );
    } );
} );

把上面代码存成 assets/js/customizer-preview.js,再注册:

add_action( 'customize_preview_init', 'mimangfei_customize_preview_js' );

function mimangfei_customize_preview_js() {
    wp_enqueue_script(
        'mimangfei-customizer',
        get_template_directory_uri() . '/assets/js/customizer-preview.js',
        array( 'jquery', 'customize-preview' ),
        '1.0.0',
        true
    );
}

依赖里一定要带 customize-preview,否则 wp.customize 对象不可用。这一步做完,配色调整就是所见即所得,和 WordPress主题开发 里讲的主题结构规范是同一套工程思路。

常见踩坑

  1. 只加 Control 不加 Setting:界面正常显示,点发布后值丢失,因为根本没有存储目标。
  2. id 不加前缀:footer_text 这种通用名,父主题已有同名 Setting 时会静默冲突,必须写成 mimangfei_footer_text。
  3. transport 设成 postMessage 但没写 JS:预览界面改了没反应,用户以为主题坏了。
  4. sanitize_callback 写错函数名:保存时报 500,Customizer 返回「无效值」,排查时先看 PHP 错误日志。
  5. type => 'option' 与 theme_mod 混淆:换 option 后取值要用 get_option(),继续用 get_theme_mod() 永远拿不到。
  6. 案例:某外贸站主题把「联系电话」做成了 Customizer 项,但 add_setting 时漏了 sanitize_callback,运营在后台填了一段带 <script> 的推广代码,保存后前台直接执行,站点被挂了跳转脚本。补上 sanitize_text_field 并清理数据库里的历史值才恢复。
  7. 在 init 里调用 get_theme_mod:太早,主题尚未完全加载,建议挂在 wp_head、wp_footer 或模板文件内。
  8. 忘了 customize_preview_init 的依赖:脚本被加载但 wp.customize is undefined,控制台报错。

总结

判断标准很简单:能用原生 Customizer 解决的(文字、颜色、开关、图片、下拉),就别引框架;需要 repeater、排版组合、字段联动时再上 Kirki 之类的方案。写完自查四件事——Setting 与 Control 成对、id 有前缀、sanitize 有回调、输出有 escaping。做完这套,客户改版权、换主色再也不会来找你,同时 主题选项面板实现方式 的选型也有了个清晰的起点。

U
UFO_PF作者

专注 WordPress 生态的实战作者,内容以「可复制、可验证」为第一原则。

留下你的想法

邮箱地址不会被公开。带 * 的为必填项。