咳咳,各位同学,今天咱们来聊聊 WordPress 主题定制器的两大利器:get_theme_mod()
和 set_theme_mod()
。 别看名字挺长,其实它们的作用很简单,就像咱们家里控制灯泡亮度的开关一样,一个负责读取亮度(get_theme_mod()
),一个负责调节亮度(set_theme_mod()
)。
咱们的目标是,扒光它们的源码,看看它们是如何跟主题定制器选项眉来眼去的。放心,不会让你头秃,我会尽量用大白话把事情讲清楚。
一、get_theme_mod()
:主题定制器数据的“读取器”
首先,咱们来看看 get_theme_mod()
的源码(WordPress 源码位于 wp-includes/theme.php
):
/**
* Retrieve a theme modification value.
*
* @since 3.4.0
*
* @param string $name Theme modification name.
* @param mixed $default Optional. Default value to return if the theme modification does not exist. Default false.
* @return mixed Theme modification value, or $default if the modification does not exist.
*/
function get_theme_mod( $name, $default = false ) {
return get_option( 'theme_mods_' . get_stylesheet(), $default )[ $name ] ?? $default;
}
是不是感觉有点短?没错,get_theme_mod()
本身只是一个“二传手”,它真正干活的是 get_option()
。咱们来拆解一下:
$name
: 这是你要读取的主题定制器选项的名称,比如'header_textcolor'
(头部文字颜色)。$default
: 如果这个选项没有设置值,就返回这个默认值。 默认值是false
。get_stylesheet()
: 这个函数会返回当前主题的样式表名称(通常就是主题的目录名)。 比如,你的主题目录是'my-awesome-theme'
,那么get_stylesheet()
就会返回'my-awesome-theme'
。'theme_mods_' . get_stylesheet()
: 这部分代码拼接出一个选项名,这个选项名是 WordPress 用来存储主题定制器选项的。 比如,当前主题是'my-awesome-theme'
,那么这个选项名就是'theme_mods_my-awesome-theme'
。get_option( 'theme_mods_' . get_stylesheet(), $default )
: 这个函数才是真正从数据库里读取选项值的。它会读取名为'theme_mods_my-awesome-theme'
的选项,如果这个选项不存在,就返回$default
。[ $name ] ?? $default
: 这是PHP7.0+的语法,叫做 NULL 合并运算符。它的意思是:如果get_option()
返回的数组中存在键名为$name
的元素,就返回这个元素的值;否则,就返回$default
。简单来说,就是从刚才读取的数组里,取出$name
对应的值,如果$name
不存在,就返回$default
。
总结:get_theme_mod()
的工作流程
- 拼接出存储主题定制器选项的选项名(
'theme_mods_' . 主题名
)。 - 使用
get_option()
从数据库中读取这个选项的值(一个数组)。 - 从这个数组中取出
$name
对应的值,如果$name
不存在,就返回$default
。
举个栗子:
假设你有一个主题,主题名是 'my-awesome-theme'
,并且你在主题定制器中设置了 'header_textcolor'
的值为 '#FF0000'
。
那么,当你调用 get_theme_mod( 'header_textcolor', '#000000' )
时,get_theme_mod()
会执行以下步骤:
- 拼接出选项名
'theme_mods_my-awesome-theme'
。 - 使用
get_option()
从数据库中读取'theme_mods_my-awesome-theme'
选项的值,假设读取到的值是array( 'header_textcolor' => '#FF0000', 'background_color' => '#FFFFFF' )
。 - 从这个数组中取出
'header_textcolor'
对应的值'#FF0000'
并返回。
如果 'header_textcolor'
没有设置值,那么 get_theme_mod()
就会返回你传入的默认值 '#000000'
。
二、set_theme_mod()
:主题定制器数据的“写入器”
接下来,咱们来看看 set_theme_mod()
的源码(WordPress 源码位于 wp-includes/theme.php
):
/**
* Modify a theme modification value.
*
* @since 3.4.0
*
* @param string $name Theme modification name.
* @param mixed $value Theme modification value.
* @return bool True if the value was successfully set. False on failure.
*/
function set_theme_mod( $name, $value ) {
$mods = get_theme_mods();
if ( null === $value ) {
unset( $mods[ $name ] );
} else {
$mods[ $name ] = $value;
}
return update_option( 'theme_mods_' . get_stylesheet(), $mods );
}
这次代码稍微长一点,但逻辑也很清晰:
$name
: 这是你要设置的主题定制器选项的名称,比如'header_textcolor'
。$value
: 这是你要设置的主题定制器选项的值,比如'#00FF00'
。get_theme_mods()
: 这个函数会返回当前主题的所有主题定制器选项,它本质上就是调用了get_option( 'theme_mods_' . get_stylesheet() )
,和get_theme_mod
差不多,只不过是返回整个数组。if ( null === $value )
: 如果$value
是null
,那么就从$mods
数组中移除$name
对应的元素。 这相当于删除一个主题定制器选项。else { $mods[ $name ] = $value; }
: 否则,就将$value
赋值给$mods
数组中$name
对应的元素。 这相当于设置或更新一个主题定制器选项。update_option( 'theme_mods_' . get_stylesheet(), $mods )
: 这个函数会将$mods
数组保存到数据库中,选项名还是'theme_mods_' . 主题名
。
总结:set_theme_mod()
的工作流程
- 获取当前主题的所有主题定制器选项(一个数组)。
- 如果
$value
是null
,就从数组中移除$name
对应的元素。 - 否则,就将
$value
赋值给数组中$name
对应的元素。 - 将修改后的数组保存到数据库中。
举个栗子:
假设你有一个主题,主题名是 'my-awesome-theme'
,并且你想要将 'header_textcolor'
设置为 '#00FF00'
。
那么,当你调用 set_theme_mod( 'header_textcolor', '#00FF00' )
时,set_theme_mod()
会执行以下步骤:
- 使用
get_theme_mods()
获取当前主题的所有主题定制器选项,假设获取到的值是array( 'background_color' => '#FFFFFF' )
。 - 将
'#00FF00'
赋值给$mods
数组中'header_textcolor'
对应的元素,得到$mods = array( 'background_color' => '#FFFFFF', 'header_textcolor' => '#00FF00' )
。 - 使用
update_option()
将$mods
数组保存到数据库中,选项名是'theme_mods_my-awesome-theme'
。
如果你调用 set_theme_mod( 'header_textcolor', null )
,那么 set_theme_mod()
会执行以下步骤:
- 使用
get_theme_mods()
获取当前主题的所有主题定制器选项,假设获取到的值是array( 'background_color' => '#FFFFFF', 'header_textcolor' => '#FF0000' )
。 - 从
$mods
数组中移除'header_textcolor'
对应的元素,得到$mods = array( 'background_color' => '#FFFFFF' )
。 - 使用
update_option()
将$mods
数组保存到数据库中,选项名是'theme_mods_my-awesome-theme'
。
三、get_theme_mods()
:获取所有主题定制选项
我们上面提到了get_theme_mods()
,它的源码也简单看一下,位于wp-includes/theme.php
:
/**
* Get all theme modification values.
*
* @since 3.4.0
*
* @return array Theme modification values.
*/
function get_theme_mods() {
return get_option( 'theme_mods_' . get_stylesheet() );
}
实际上就是调用了get_option()
,获取'theme_mods_' . get_stylesheet()
对应的值,返回的是一个包含所有主题定制选项的数组。
四、remove_theme_mod()
:移除单个主题定制选项
虽然 WordPress 没有直接提供 remove_theme_mod()
函数,但我们可以使用 set_theme_mod()
将选项的值设置为 null
来达到相同的效果。
例如:
set_theme_mod( 'header_textcolor', null );
这行代码会从数据库中删除 'header_textcolor'
这个主题定制器选项。
五、主题定制器选项是如何与主题定制器界面交互的?
好,现在咱们来聊聊主题定制器选项是如何与主题定制器界面交互的。这部分涉及到更多主题定制器的 API,咱们先简单了解一下。
1. WP_Customize_Manager
类
WordPress 主题定制器是由 WP_Customize_Manager
类来管理的。这个类负责注册主题定制器面板、区块、设置和控件。
2. add_setting()
方法
add_setting()
方法用于注册一个主题定制器设置。设置定义了选项的类型、验证规则和传输方式。
global $wp_customize;
$wp_customize->add_setting( 'header_textcolor', array(
'default' => '#000000',
'sanitize_callback' => 'sanitize_hex_color',
'transport' => 'postMessage', // 或 'refresh'
) );
'header_textcolor'
:设置的名称,这个名称会和get_theme_mod()
和set_theme_mod()
的第一个参数对应。'default'
:默认值。'sanitize_callback'
:用于对用户输入进行验证和清理的回调函数。'transport'
:传输方式。'postMessage'
表示使用 JavaScript 实时预览,'refresh'
表示刷新整个页面。
3. add_control()
方法
add_control()
方法用于注册一个主题定制器控件。控件是用户与设置交互的界面元素,比如文本框、颜色选择器、单选按钮等。
$wp_customize->add_control( new WP_Customize_Color_Control( $wp_customize, 'header_textcolor', array(
'label' => __( 'Header Text Color', 'my-awesome-theme' ),
'section' => 'title_tagline', // 所属的区块
'settings' => 'header_textcolor', // 关联的设置
) ) );
'header_textcolor'
:控件的 ID。'label'
:控件的标签。'section'
:控件所属的区块。'settings'
:与控件关联的设置。
4. 交互流程
当用户在主题定制器界面中修改一个选项时,会发生以下流程:
- 用户在控件中输入新的值。
- JavaScript 代码将新的值发送到服务器。
- 服务器端的 PHP 代码调用
set_theme_mod()
函数,将新的值保存到数据库中。 - 如果设置的
transport
是'postMessage'
,那么 JavaScript 代码会使用postMessage
API 将新的值发送到预览窗口,实现实时预览。 - 如果设置的
transport
是'refresh'
,那么整个预览窗口会刷新,显示新的值。
当主题加载时,会发生以下流程:
- 主题调用
get_theme_mod()
函数,从数据库中读取选项的值。 - 主题使用读取到的值来渲染页面。
六、实战演练:自定义一个主题定制器选项
为了更好地理解 get_theme_mod()
和 set_theme_mod()
的用法,咱们来创建一个自定义的主题定制器选项。
1. 注册设置和控件
在你的主题的 functions.php
文件中,添加以下代码:
<?php
function my_awesome_theme_customize_register( $wp_customize ) {
// 1. 注册一个设置
$wp_customize->add_setting( 'my_custom_text', array(
'default' => 'Hello, World!',
'sanitize_callback' => 'sanitize_text_field',
'transport' => 'refresh',
) );
// 2. 注册一个控件
$wp_customize->add_control( 'my_custom_text', array(
'label' => __( 'Custom Text', 'my-awesome-theme' ),
'section' => 'title_tagline', // 放在 "站点身份" 区块
'type' => 'text', // 文本输入框
'settings' => 'my_custom_text',
) );
}
add_action( 'customize_register', 'my_awesome_theme_customize_register' );
这段代码会在主题定制器中添加一个名为 "Custom Text" 的文本输入框,并将它的值保存到 'my_custom_text'
这个主题定制器选项中。
2. 在主题中使用 get_theme_mod()
在你的主题的某个模板文件中(比如 header.php
),添加以下代码:
<?php
$custom_text = get_theme_mod( 'my_custom_text', 'Default Text' );
echo esc_html( $custom_text );
?>
这段代码会从数据库中读取 'my_custom_text'
选项的值,并将其显示在页面上。 如果没有设置值,则显示 "Default Text"。
3. 测试
现在,你可以打开主题定制器,找到 "站点身份" 区块,修改 "Custom Text" 文本框中的值,然后保存。 刷新页面,你应该能看到页面上显示了你修改后的文本。
七、代码示例
下面是一个更完整的示例,展示了如何在主题定制器中添加一个颜色选择器,并将选择的颜色应用到页面的背景色上。
1. 注册设置和控件
<?php
function my_awesome_theme_customize_register( $wp_customize ) {
// 1. 添加一个区块 (Section)
$wp_customize->add_section( 'my_custom_section', array(
'title' => __( 'Custom Background', 'my-awesome-theme' ),
'priority' => 200, // 显示优先级
) );
// 2. 注册一个颜色设置
$wp_customize->add_setting( 'my_background_color', array(
'default' => '#FFFFFF',
'sanitize_callback' => 'sanitize_hex_color',
'transport' => 'postMessage',
) );
// 3. 注册一个颜色控件
$wp_customize->add_control( new WP_Customize_Color_Control( $wp_customize, 'my_background_color', array(
'label' => __( 'Background Color', 'my-awesome-theme' ),
'section' => 'my_custom_section', // 放在我们自定义的区块里
'settings' => 'my_background_color',
) ) );
// 4. 添加 JavaScript 实时预览
wp_enqueue_script( 'my-awesome-theme-customizer', get_template_directory_uri() . '/js/customizer.js', array( 'customize-preview' ), false, true );
}
add_action( 'customize_register', 'my_awesome_theme_customize_register' );
2. 在 customizer.js
中添加 JavaScript 代码
在你的主题的 js
目录下创建一个名为 customizer.js
的文件,并添加以下代码:
( function( $ ) {
wp.customize( 'my_background_color', function( value ) {
value.bind( function( newval ) {
$( 'body' ).css( 'background-color', newval );
} );
} );
} )( jQuery );
这段代码会监听 'my_background_color'
设置的变化,并将新的颜色值应用到 body
元素的背景色上。
3. 在主题中使用 get_theme_mod()
在你的主题的 header.php
文件中,添加以下代码:
<style type="text/css">
body {
background-color: <?php echo get_theme_mod( 'my_background_color', '#FFFFFF' ); ?>;
}
</style>
这段代码会将 'my_background_color'
选项的值作为 body
元素的背景色。
表格总结:get_theme_mod()
vs set_theme_mod()
函数 | 作用 | 参数 | 返回值 |
---|---|---|---|
get_theme_mod() |
读取主题定制器选项的值 | $name (string): 选项名称。$default (mixed, optional): 默认值,如果选项不存在则返回。默认为 false 。 |
选项的值 (mixed)。如果选项不存在,则返回 $default 。 |
set_theme_mod() |
设置/更新主题定制器选项的值,或删除选项 (设置为 null ) |
$name (string): 选项名称。$value (mixed): 要设置的值。如果设置为 null ,则删除该选项。 |
true (bool): 如果成功设置/更新/删除选项。false (bool): 如果设置/更新/删除选项失败。 |
八、注意事项
- 数据验证: 一定要对用户输入的数据进行验证和清理,以防止安全漏洞。 可以使用 WordPress 提供的
sanitize_text_field()
,sanitize_hex_color()
,absint()
等函数。 - 传输方式: 选择合适的传输方式。 如果需要实时预览,可以使用
'postMessage'
。 如果不需要实时预览,可以使用'refresh'
。 - 性能: 不要在主题中过度使用主题定制器选项,这可能会影响性能。 尽量将常用的选项缓存在内存中。
好了,今天的讲座就到这里。 希望大家通过今天的学习,能够更好地理解和使用 get_theme_mod()
和 set_theme_mod()
函数,打造出更加个性化的 WordPress 主题。 下课!