咳咳,麦克风试音,1 2 3… 大家好!我是老码农,今天咱们聊聊 WordPress 后台设置选项的“户口”是怎么上的,也就是 register_setting()
函数的工作原理。
说白了,register_setting()
就是个“登记员”,它负责告诉 WordPress:“嘿,老兄,我这里有几个新来的设置选项,你得给它们在数据库里安排个位置,顺便让它们在后台页面上露个脸。”
咱们先从最简单的用法开始,然后逐步深入,看看这个函数背后到底藏着哪些玄机。
1. register_setting()
的基本结构
register_setting()
函数的原型是这样的:
register_setting( string $option_group, string $option_name, array $args = array() );
$option_group
: 选项组名,它就像一个“文件夹”,把相关的设置选项放在一起,方便管理。$option_name
: 选项名,每个设置选项的唯一标识符,就像它的“身份证号”。$args
: 一个可选的参数数组,里面可以设置一些额外的选项,比如验证回调函数。
2. 简单示例:注册一个文本框设置
假设我们要创建一个“网站标题背景颜色”的设置选项,让用户可以自定义网站标题的背景颜色。我们可以这样做:
<?php
add_action( 'admin_init', 'my_theme_register_settings' );
function my_theme_register_settings() {
register_setting( 'my_theme_options', 'my_theme_title_bg_color', 'sanitize_hex_color' );
}
?>
这段代码做了什么?
add_action( 'admin_init', 'my_theme_register_settings' );
: 这行代码告诉 WordPress,在后台初始化的时候(admin_init
钩子),执行my_theme_register_settings()
函数。register_setting( 'my_theme_options', 'my_theme_title_bg_color', 'sanitize_hex_color' );
: 这行代码是核心。'my_theme_options'
: 选项组名,我们把它叫做my_theme_options
。你可以随便起个名字,只要保证唯一性就好。'my_theme_title_bg_color'
: 选项名,我们把它叫做my_theme_title_bg_color
。 将来可以通过这个名字来获取和更新这个设置的值。'sanitize_hex_color'
: 验证回调函数,用来对用户输入的值进行验证和过滤。sanitize_hex_color()
是 WordPress 内置的函数,用来确保用户输入的是有效的十六进制颜色值。
3. 验证回调函数:守门员的角色
验证回调函数非常重要,它就像一个“守门员”,防止用户输入一些不合法的数据,导致程序出错或者安全问题。
如果没有指定验证回调函数,WordPress 会默认使用 sanitize_text_field()
函数,它会对用户输入的值进行简单的过滤,去除 HTML 标签和特殊字符。
除了使用 WordPress 内置的验证函数,我们也可以自定义验证函数。例如:
<?php
function my_theme_validate_title_bg_color( $input ) {
// 如果用户输入的值不是有效的十六进制颜色值,就返回默认值 #ffffff
if ( ! preg_match( '/^#([0-9a-f]{3}){1,2}$/i', $input ) ) {
add_settings_error(
'my_theme_title_bg_color',
'invalid_color',
'请输入有效的十六进制颜色值,例如 #ffffff',
'error'
);
return '#ffffff';
}
return $input;
}
add_action( 'admin_init', 'my_theme_register_settings' );
function my_theme_register_settings() {
register_setting( 'my_theme_options', 'my_theme_title_bg_color', 'my_theme_validate_title_bg_color' );
}
?>
这段代码做了什么?
my_theme_validate_title_bg_color( $input )
: 自定义的验证回调函数。$input
: 用户输入的值。preg_match( '/^#([0-9a-f]{3}){1,2}$/i', $input )
: 使用正则表达式判断用户输入的值是否是有效的十六进制颜色值。add_settings_error()
: 如果用户输入的值不合法,就添加一个错误信息,显示在后台页面上。return '#ffffff';
: 如果用户输入的值不合法,就返回默认值#ffffff
。
register_setting( 'my_theme_options', 'my_theme_title_bg_color', 'my_theme_validate_title_bg_color' );
: 在register_setting()
函数中指定使用我们自定义的验证函数。
4. 选项组:设置选项的“家”
选项组就像一个“文件夹”,把相关的设置选项放在一起。 在后台页面上,通常会把同一个选项组的设置选项放在同一个表单里。
WordPress 内置了一些常用的选项组,比如 general
(常规选项)、reading
(阅读选项)、writing
(撰写选项)等等。 我们也可以自定义选项组。
5. $args
参数:更多配置选项
register_setting()
函数的第三个参数 $args
是一个数组,里面可以设置一些额外的选项。
参数名 | 类型 | 描述 |
---|---|---|
type |
string | 设置选项的数据类型。 默认是 'string' 。常用的类型有 'string' 、'integer' 、'number' 、'boolean' 、'array' 、'object' 。 WordPress 会根据这个类型对用户输入的值进行验证。 |
description |
string | 设置选项的描述信息,显示在后台页面上。 |
sanitize_callback |
mixed | 验证回调函数。 如果指定了这个参数,register_setting() 函数会优先使用这个参数指定的验证函数,而不是使用第三个参数指定的验证函数。 |
show_in_rest |
bool | 是否在 REST API 中显示这个设置选项。 默认是 false 。 如果设置为 true ,就可以通过 REST API 来获取和更新这个设置的值。 |
default |
mixed | 设置选项的默认值。 |
例如:
<?php
add_action( 'admin_init', 'my_theme_register_settings' );
function my_theme_register_settings() {
register_setting(
'my_theme_options',
'my_theme_title_font_size',
array(
'type' => 'integer',
'description' => '网站标题字体大小(像素)',
'sanitize_callback' => 'absint',
'default' => 16,
'show_in_rest' => true,
)
);
}
?>
这段代码做了什么?
'type' => 'integer'
: 指定my_theme_title_font_size
选项的数据类型是整数。'description' => '网站标题字体大小(像素)'
: 设置选项的描述信息,显示在后台页面上。'sanitize_callback' => 'absint'
: 指定验证回调函数是absint()
。absint()
是 WordPress 内置的函数,用来将用户输入的值转换为绝对整数。'default' => 16
: 设置选项的默认值是 16。'show_in_rest' => true
: 允许通过 REST API 来获取和更新my_theme_title_font_size
选项的值。
6. 如何在后台页面上显示设置选项?
register_setting()
函数只是负责注册设置选项,并不会自动在后台页面上显示它们。 我们需要手动编写代码,在后台页面上显示设置选项的表单。
通常,我们会使用 add_settings_section()
和 add_settings_field()
函数来创建设置选项的表单。
<?php
add_action( 'admin_menu', 'my_theme_add_admin_menu' );
add_action( 'admin_init', 'my_theme_register_settings' );
function my_theme_add_admin_menu() {
add_theme_page(
'主题设置',
'主题设置',
'manage_options',
'my-theme-options',
'my_theme_options_page'
);
}
function my_theme_options_page() {
?>
<div class="wrap">
<h1>主题设置</h1>
<form method="post" action="options.php">
<?php
settings_fields( 'my_theme_options' ); // 输出选项组的隐藏字段
do_settings_sections( 'my-theme-options' ); // 输出选项组的表单
submit_button(); // 输出提交按钮
?>
</form>
</div>
<?php
}
function my_theme_register_settings() {
register_setting(
'my_theme_options',
'my_theme_title_bg_color',
'sanitize_hex_color'
);
add_settings_section(
'my_theme_title_section',
'网站标题设置',
'my_theme_title_section_callback',
'my-theme-options'
);
add_settings_field(
'my_theme_title_bg_color',
'背景颜色',
'my_theme_title_bg_color_callback',
'my-theme-options',
'my_theme_title_section'
);
register_setting(
'my_theme_options',
'my_theme_title_font_size',
array(
'type' => 'integer',
'description' => '网站标题字体大小(像素)',
'sanitize_callback' => 'absint',
'default' => 16,
'show_in_rest' => true,
)
);
add_settings_field(
'my_theme_title_font_size',
'字体大小',
'my_theme_title_font_size_callback',
'my-theme-options',
'my_theme_title_section'
);
}
function my_theme_title_section_callback() {
echo '<p>在这里可以设置网站标题的样式。</p>';
}
function my_theme_title_bg_color_callback() {
$value = get_option( 'my_theme_title_bg_color', '#ffffff' );
?>
<input type="color" name="my_theme_title_bg_color" value="<?php echo esc_attr( $value ); ?>">
<?php
}
function my_theme_title_font_size_callback() {
$value = get_option( 'my_theme_title_font_size', 16 );
?>
<input type="number" name="my_theme_title_font_size" value="<?php echo esc_attr( $value ); ?>">
<?php
}
?>
这段代码比较长,我们来逐步分析:
add_action( 'admin_menu', 'my_theme_add_admin_menu' );
: 在后台菜单中添加一个“主题设置”页面。my_theme_add_admin_menu()
: 创建后台菜单项。my_theme_options_page()
: 显示“主题设置”页面的内容。settings_fields( 'my_theme_options' );
: 输出选项组的隐藏字段,用于安全验证。do_settings_sections( 'my-theme-options' );
: 输出选项组的表单,根据之前定义的 section 和 field 来显示设置选项。submit_button();
: 输出提交按钮。
add_settings_section()
: 创建一个设置选项的 section。'my_theme_title_section'
: section 的 ID。'网站标题设置'
: section 的标题,显示在后台页面上。'my_theme_title_section_callback'
: section 的回调函数,用于输出 section 的描述信息。'my-theme-options'
: 页面 ID,指定 section 显示在哪个页面上。
add_settings_field()
: 创建一个设置选项的 field。'my_theme_title_bg_color'
: field 的 ID,与register_setting()
函数中的选项名一致。'背景颜色'
: field 的标题,显示在后台页面上。'my_theme_title_bg_color_callback'
: field 的回调函数,用于输出 field 的 HTML 代码。'my-theme-options'
: 页面 ID,指定 field 显示在哪个页面上。'my_theme_title_section'
: section ID,指定 field 显示在哪个 section 中。
my_theme_title_section_callback()
: 输出 section 的描述信息。my_theme_title_bg_color_callback()
: 输出“背景颜色”设置选项的 HTML 代码。 这里使用<input type="color">
创建一个颜色选择器。get_option( 'my_theme_title_bg_color', '#ffffff' )
: 获取my_theme_title_bg_color
选项的值。 如果选项不存在,就返回默认值#ffffff
。esc_attr()
: 对输出的属性值进行转义,防止 XSS 攻击。
my_theme_title_font_size_callback()
: 输出 "字体大小" 设置选项的 HTML 代码。 这里使用<input type="number">
创建一个数字输入框。
7. 如何获取设置选项的值?
可以使用 get_option()
函数来获取设置选项的值。
<?php
$title_bg_color = get_option( 'my_theme_title_bg_color', '#ffffff' );
$title_font_size = get_option( 'my_theme_title_font_size', 16 );
?>
get_option( 'my_theme_title_bg_color', '#ffffff' )
: 获取my_theme_title_bg_color
选项的值。 如果选项不存在,就返回默认值#ffffff
。get_option( 'my_theme_title_font_size', 16 )
: 获取my_theme_title_font_size
选项的值。 如果选项不存在,就返回默认值16
。
8. register_setting()
的源码剖析
咱们现在来扒一扒 register_setting()
函数的源码,看看它到底做了什么。
(由于 WordPress 版本更新迭代快,以下代码片段基于 WordPress 相对较新的版本,具体请参考你使用的 WordPress 版本)
首先,register_setting()
函数位于 wp-admin/includes/plugin.php
文件中。 它的主要逻辑如下:
function register_setting( $option_group, $option_name, $sanitize_callback = '', $deprecated = false ) {
global $new_whitelist_options;
// Back compat for the $deprecated argument.
if ( ! is_scalar( $sanitize_callback ) && ! is_callable( $sanitize_callback ) && false !== $deprecated ) {
_deprecated_argument( __FUNCTION__, '4.7.0', sprintf(
/* translators: 1: The name of the function. 2: The name of the argument. */
__( 'The third argument to %1$s must be a string or callable, not boolean. To pass a boolean as a default value, use the %2$s argument to the %1$s function instead.' ),
'register_setting()',
'default'
) );
$args = $sanitize_callback;
$sanitize_callback = $deprecated;
} else {
$args = func_get_args();
$args = ( isset( $args[2] ) && is_array( $args[2] ) ) ? $args[2] : array();
}
$args = wp_parse_args( $args, array(
'type' => 'string',
'description' => '',
'sanitize_callback' => $sanitize_callback,
'show_in_rest' => false,
'default' => null,
) );
$new_whitelist_options[ $option_group ][ $option_name ] = true;
add_action( 'sanitize_option_' . $option_name, array( _WP_Dependency::get_instance(), 'sanitize_option' ), 10, 2 );
// Register the setting to the REST API.
if ( ! empty( $args['show_in_rest'] ) ) {
register_rest_field( 'options', $option_name, array(
'get_callback' => function() use ( $option_name ) {
return get_option( $option_name );
},
'update_callback' => function( $value ) use ( $option_name ) {
return update_option( $option_name, $value );
},
'schema' => array(
'type' => $args['type'],
'description' => $args['description'],
'default' => $args['default'],
),
) );
}
}
这段代码做了什么?
- 兼容性处理: 检查参数,处理一些旧版本的兼容性问题。
- 参数解析: 使用
wp_parse_args()
函数将传入的参数和默认参数合并,得到最终的参数数组$args
。 - 添加到白名单: 将选项组和选项名添加到
$new_whitelist_options
全局变量中。 这个变量用于存储所有注册的设置选项。 - 注册验证钩子: 使用
add_action()
函数注册一个钩子,当保存option_name
选项时,会执行_WP_Dependency::sanitize_option()
函数进行验证。 - 注册 REST API 字段: 如果
$args['show_in_rest']
为true
,则使用register_rest_field()
函数将该选项注册到 REST API 中,使其可以通过 REST API 进行访问。
_WP_Dependency::sanitize_option()
函数
_WP_Dependency::sanitize_option()
函数负责调用验证回调函数,对用户输入的值进行验证和过滤。
public function sanitize_option( $value, $option ) {
// Get the registered setting for the option.
$registered_setting = $this->get_registered_setting( $option );
// If no registered setting, return the value as is.
if ( ! $registered_setting ) {
return $value;
}
// Get the sanitize callback.
$sanitize_callback = $registered_setting['sanitize_callback'];
// If no sanitize callback, return the value as is.
if ( ! $sanitize_callback ) {
return $value;
}
// If sanitize callback is a string, check if it is a valid function.
if ( is_string( $sanitize_callback ) && ! is_callable( $sanitize_callback ) ) {
return $value;
}
// Call the sanitize callback.
$value = call_user_func( $sanitize_callback, $value );
return $value;
}
这段代码做了什么?
- 获取注册的设置: 调用
$this->get_registered_setting()
函数获取选项的注册信息。 - 检查验证回调函数: 检查是否存在验证回调函数。 如果没有,直接返回原始值。
- 调用验证回调函数: 使用
call_user_func()
函数调用验证回调函数,对用户输入的值进行验证和过滤。
总结
register_setting()
函数就像 WordPress 后台设置选项的“户籍管理员”,它负责将设置选项注册到系统中,并指定验证回调函数,确保数据的安全性。 通过 add_settings_section()
和 add_settings_field()
函数,我们可以将这些设置选项在后台页面上显示出来,让用户可以自定义网站的各种设置。 最后,可以使用 get_option()
函数来获取设置选项的值,并在主题或插件中使用。
希望这次的“讲座”能帮助大家更好地理解 register_setting()
函数的工作原理。 下次有机会,咱们再聊聊 WordPress 的其他有趣话题! 谢谢大家!