各位观众老爷们,今天咱们来聊聊 WordPress 主题定制器这玩意儿,特别是里面的 WP_Customize_Manager
类,以及它是怎么耍花招,让我们能用 add_setting()
和 add_control()
变出各种主题选项的。准备好,咱们要开始扒源码了!
一、定制器:你的主题魔镜
首先,得明白主题定制器是干嘛的。你可以把它想象成一面魔镜,但不是让你问“谁是世界上最美丽的人”,而是让你实时调整主题的外观,比如颜色、字体、布局,然后立马看到效果。这种所见即所得的体验,简直不要太爽!
WordPress 提供了 WP_Customize_Manager
类,专门负责管理这个魔镜。它就像一个总指挥,协调各种设置(settings)、控制(controls)和面板(panels),让你轻松定制主题。
二、WP_Customize_Manager
:幕后大 BOSS
WP_Customize_Manager
类是定制器的核心。它负责:
- 启动定制器界面
- 注册设置、控制和面板
- 处理 AJAX 请求
- 保存定制选项
要访问这个类,你得先判断它是否存在,通常在 customize_register
钩子中进行:
add_action( 'customize_register', 'my_theme_customize_register' );
function my_theme_customize_register( $wp_customize ) {
// $wp_customize 就是 WP_Customize_Manager 的实例
// 现在你可以用它来添加设置、控制和面板了
}
三、add_setting()
:定义主题选项
add_setting()
方法用来定义一个主题选项。它告诉 WordPress,我们需要存储一个值,并为这个值分配一个 ID。这个 ID 就像一个房间号,以后我们就可以通过它来找到这个房间里的东西(也就是选项的值)。
add_setting()
方法接受两个参数:
$id
:选项的 ID,必须是唯一的。$args
:一个数组,包含选项的各种属性。
$wp_customize->add_setting(
'my_theme_accent_color', // 选项 ID
array(
'default' => '#007bff', // 默认值
'type' => 'theme_mod', // 存储类型,theme_mod 或 option
'capability' => 'edit_theme_options', // 权限
'transport' => 'refresh', // 刷新方式,refresh 或 postMessage
'sanitize_callback' => 'sanitize_hex_color', // 清理回调函数
)
);
咱们来分解一下 $args
数组里的几个关键属性:
属性 | 描述 |
---|---|
default |
选项的默认值。如果没有设置任何值,就使用这个默认值。 |
type |
选项的存储类型。theme_mod 表示存储在主题的设置中,option 表示存储在 WordPress 的 wp_options 表中。通常情况下,主题选项使用 theme_mod 。 |
capability |
允许修改这个选项的用户权限。edit_theme_options 表示只有具有编辑主题选项权限的用户才能修改。 |
transport |
刷新方式。refresh 表示页面需要重新加载才能看到效果,postMessage 表示可以通过 JavaScript 实时更新页面,无需重新加载。postMessage 体验更好,但需要编写额外的 JavaScript 代码来处理。 |
sanitize_callback |
清理回调函数。这个函数会在保存选项值之前被调用,用来清理用户输入,防止恶意代码注入。sanitize_hex_color 是一个 WordPress 内置的函数,用来清理十六进制颜色值。 |
四、add_control()
:创建控制面板
光有设置还不够,还得有个控制面板让用户来修改选项的值。add_control()
方法就是用来创建控制面板的。它会在定制器界面上显示一个表单元素,让用户输入或选择值。
add_control()
方法也接受两个参数:
$id
:控制的 ID,必须是唯一的。$args
:一个数组,包含控制的各种属性。
$wp_customize->add_control(
new WP_Customize_Color_Control( // 控制类型
$wp_customize,
'my_theme_accent_color', // 控制 ID,与 setting 的 ID 相同
array(
'label' => __( 'Accent Color', 'my-theme' ), // 标签
'section' => 'colors', // 所属的 section
'settings' => 'my_theme_accent_color', // 关联的 setting ID
)
)
);
这里有点不一样,第一个参数不是一个简单的字符串,而是一个 WP_Customize_Color_Control
类的实例。这是因为 WordPress 提供了多种控制类型,比如文本框、下拉列表、单选按钮等等。每种控制类型都有自己的类。
咱们来看看 $args
数组里的几个关键属性:
属性 | 描述 |
---|---|
label |
控制的标签,也就是在控制面板上显示的文字。 |
section |
控制所属的 section。section 是定制器界面的一个分组,用来组织相关的控制。WordPress 默认提供了一些 section,比如 colors 、header_image 、background_image 等等。你也可以自定义 section。 |
settings |
关联的 setting ID。这个属性告诉 WordPress,这个控制是用来修改哪个 setting 的值的。 |
五、控制类型:各式各样的表单元素
WordPress 提供了多种控制类型,满足不同的需求:
WP_Customize_Control
:基类,所有控制类型都继承自它。WP_Customize_Color_Control
:颜色选择器。WP_Customize_Image_Control
:图片上传器。WP_Customize_Upload_Control
:文件上传器。WP_Customize_Media_Control
:媒体上传器 (支持图片、音频、视频)。WP_Customize_Cropped_Image_Control
:裁剪图片上传器。WP_Customize_Background_Image_Control
:背景图片上传器。WP_Customize_Header_Image_Control
:头部图片上传器。WP_Customize_Dropdown_Pages_Control
:页面下拉列表。
如果你觉得这些控制类型不够用,还可以自定义控制类型。这需要你创建一个继承自 WP_Customize_Control
的类,并重写 render_content()
方法来渲染控制的内容。
六、面板(Panels)和 Section:定制器的组织者
为了让定制器界面更清晰,我们可以使用面板(Panels)和 Section 来组织控制。
- 面板(Panels): 面板是最高级别的分组,可以包含多个 Section。你可以把相关的 Section 放在同一个面板里。
- Section: Section 是控制的分组,用来组织相关的控制。
使用 add_panel()
方法可以添加面板:
$wp_customize->add_panel(
'my_theme_general_settings',
array(
'title' => __( 'General Settings', 'my-theme' ),
'description' => __( 'General settings for my theme', 'my-theme' ),
'priority' => 10,
)
);
使用 add_section()
方法可以添加 Section:
$wp_customize->add_section(
'my_theme_header_settings',
array(
'title' => __( 'Header Settings', 'my-theme' ),
'description' => __( 'Settings for the header', 'my-theme' ),
'priority' => 20,
'panel' => 'my_theme_general_settings', // 所属的 panel ID
)
);
注意,Section 可以属于一个 Panel,也可以不属于任何 Panel。
七、get_theme_mod()
:取出主题选项的值
当我们定义了设置和控制,用户就可以在定制器界面上修改选项的值了。那么,我们如何在主题中使用这些值呢?
答案是使用 get_theme_mod()
函数。
$accent_color = get_theme_mod( 'my_theme_accent_color', '#007bff' ); // 获取选项的值,第二个参数是默认值
echo '<style>';
echo 'a { color: ' . esc_attr( $accent_color ) . '; }';
echo '</style>';
get_theme_mod()
函数接受两个参数:
$name
:选项的 ID,与add_setting()
方法的第一个参数相同。$default
:选项的默认值。如果选项没有设置任何值,就返回这个默认值。
八、postMessage
:实时预览的魔法
前面提到过,transport
属性可以设置为 postMessage
,实现实时预览的效果。但这需要我们编写额外的 JavaScript 代码来处理。
首先,在 add_setting()
方法中,将 transport
属性设置为 postMessage
:
$wp_customize->add_setting(
'my_theme_accent_color',
array(
'default' => '#007bff',
'type' => 'theme_mod',
'capability' => 'edit_theme_options',
'transport' => 'postMessage', // 设置为 postMessage
'sanitize_callback' => 'sanitize_hex_color',
)
);
然后,在 JavaScript 文件中,监听 customize-preview-init
事件,并使用 wp.customize()
API 来获取选项的值,并更新页面:
( function( $ ) {
wp.customize( 'my_theme_accent_color', function( value ) {
value.bind( function( newval ) {
$( 'a' ).css( 'color', newval );
} );
} );
} )( jQuery );
这段代码的意思是:
- 监听
my_theme_accent_color
选项的变化。 - 当选项的值发生变化时,执行回调函数。
- 在回调函数中,获取新的值
newval
。 - 使用 jQuery 将
a
标签的颜色设置为新的值。
九、完整代码示例
add_action( 'customize_register', 'my_theme_customize_register' );
function my_theme_customize_register( $wp_customize ) {
// 1. 添加面板
$wp_customize->add_panel(
'my_theme_general_settings',
array(
'title' => __( 'General Settings', 'my-theme' ),
'description' => __( 'General settings for my theme', 'my-theme' ),
'priority' => 10,
)
);
// 2. 添加 Section
$wp_customize->add_section(
'my_theme_header_settings',
array(
'title' => __( 'Header Settings', 'my-theme' ),
'description' => __( 'Settings for the header', 'my-theme' ),
'priority' => 20,
'panel' => 'my_theme_general_settings', // 所属的 panel ID
)
);
// 3. 添加 Setting
$wp_customize->add_setting(
'my_theme_accent_color',
array(
'default' => '#007bff',
'type' => 'theme_mod',
'capability' => 'edit_theme_options',
'transport' => 'postMessage',
'sanitize_callback' => 'sanitize_hex_color',
)
);
// 4. 添加 Control
$wp_customize->add_control(
new WP_Customize_Color_Control(
$wp_customize,
'my_theme_accent_color',
array(
'label' => __( 'Accent Color', 'my-theme' ),
'section' => 'my_theme_header_settings', // 所属的 section
'settings' => 'my_theme_accent_color', // 关联的 setting ID
)
)
);
}
// 5. 获取选项的值并应用
add_action( 'wp_head', 'my_theme_accent_color_css' );
function my_theme_accent_color_css() {
$accent_color = get_theme_mod( 'my_theme_accent_color', '#007bff' );
echo '<style>';
echo 'a { color: ' . esc_attr( $accent_color ) . '; }';
echo '</style>';
}
// 6. JavaScript 代码 (enqueue 到主题)
add_action( 'customize_preview_init', 'my_theme_customize_preview_js' );
function my_theme_customize_preview_js() {
wp_enqueue_script(
'my-theme-customize-preview',
get_template_directory_uri() . '/js/customize-preview.js',
array( 'customize-preview', 'jquery' ),
'',
true
);
}
/js/customize-preview.js
文件内容:
( function( $ ) {
wp.customize( 'my_theme_accent_color', function( value ) {
value.bind( function( newval ) {
$( 'a' ).css( 'color', newval );
} );
} );
} )( jQuery );
十、总结
今天咱们一起扒了 WordPress WP_Customize_Manager
类的源码,了解了如何通过 add_setting()
和 add_control()
创建主题定制器选项。简单来说,就是:
- 用
add_setting()
定义选项,告诉 WordPress 我们要存储一个值。 - 用
add_control()
创建控制面板,让用户修改选项的值。 - 用
get_theme_mod()
获取选项的值,并在主题中使用。 - 如果想要实时预览的效果,可以使用
postMessage
和 JavaScript。
希望这次的讲解能让你对 WordPress 主题定制器有更深入的了解。下次再见!