关于WordPress设置API
在WordPress v2.7中添加了设置API,它允许开发人员创建管理选项页面。界面风格与WordPress后台风格保持一致,只是它使用起来并不那么简单。你不能只定义一个设置数组,您需要编写自己的字段并保存方法。
首先注册一个设置页
视菜单位置的不同,我们需要自行选择命令,比如:
add_menu_page
add_submenu_page
add_theme_page
下面这个案例选择了使用add_menu_page
,而这个设置项会出现在后台主菜单上;
/**
* Add a new options page named "My Options".
*/
function myprefix_register_options_page() {
add_menu_page(
'My Options',
'My Options',
'manage_options',
'my_options',
'my_options_page_html'
);
}
add_action( 'admin_menu', 'myprefix_register_options_page' );
/**
* The "My Options" page html.
*/
function my_options_page_html() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
if ( isset( $_GET['settings-updated'] ) ) {
add_settings_error(
'my_options_mesages',
'my_options_message',
esc_html__( 'Settings Saved', 'text_domain' ),
'updated'
);
}
settings_errors( 'my_options_mesages' );
?>
<div class="wrap">
<h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
<form action="options.php" method="post">
<?php
settings_fields( 'my_options_group' );
do_settings_sections( 'my_options' );
submit_button( 'Save Settings' );
?>
</form>
</div>
<?php
}
注册与添加设置项
这里的案例展现了一个数组类型的设置项的创建,我们创建一个设置项,然后将其作为一个数组,设置项目较多的时候,数组形式感觉更易于管理,也不容易让options变得臃肿。首先我们注册设置项:
/**
* Register our settings.
*/
function myprefix_register_settings() {
register_setting( 'my_options_group', 'my_options' );
}
add_action( 'admin_init', 'myprefix_register_settings' );
添加设置项元素,my_options
是数组名,而my_option_1
则是其中的一个数组成员;
/**
* Register our settings.
*/
function myprefix_register_settings() {
register_setting( 'my_options', 'my_options' );
add_settings_section(
'my_options_sections',
false,
false,
'my_options'
);
add_settings_field(
'my_option_1',
esc_html__( 'My Option 1', 'text_domain' ),
'render_my_option_1_field',
'my_options',
'my_options_sections',
[
'label_for' => 'my_option_1',
]
);
}
add_action( 'admin_init', 'myprefix_register_settings' );
数据成功设置之后,我们需要在面板上显示它,所以需要一个回调函数,这样在下次进入设置页的时候,您能很直观的看到当前的设置数据;
/**
* Render the "my_option_1" field.
*/
function render_my_option_1_field( $args ) {
$value = get_option( 'my_options' )[$args['label_for']] ?? '';
?>
<input
type="text"
id="<?php echo esc_attr( $args['label_for'] ); ?>"
name="my_options[<?php echo esc_attr( $args['label_for'] ); ?>]"
value="<?php echo esc_attr( $value ); ?>">
<p class="description"><?php esc_html_e( 'This is a description for our field.', 'text_domain' ); ?></p>
<?php
}
清理用户输入
出于安全原因,对保存到数据库的数据进行清理总是很重要的。为此,我们要回到我们的register_setting
函数并添加一些额外的参数:
register_setting( 'my_options_group', 'my_options', [
'sanitize_callback' => 'my_options_sanitize_fields',
'default' => []
] );
用于清理数据的回调函数:
/**
* Sanitize fields before adding to the database.
*/
function my_options_sanitize_fields( $value ) {
$value = (array) $value;
if ( ! empty( $value['my_option_1'] ) ) {
$value['my_option_1'] = sanitize_text_field( $value['my_option_1'] );
}
return $value;
}
此函数在传递到数据库之前检查选项值,检查my_option_1是否存在并清理该值。如果您想将相同的消毒应用于选项组中的每个选项 (您的字段将被保存为数组),您可以这样做:
/**
* Sanitize fields before adding to the database.
*/
function my_options_sanitize_fields( $value ) {
return array_map( 'sanitize_text_field', $value );
}
如何获取保存的选项值
现在您知道如何在WordPress中创建自己的自定义选项面板,下一步是使用您的自定义选项值。这将使用get_option
功能。示例:
$my_option_1 = get_option( 'my_options' )['my_option_1'] ?? '';
您可能会注意到这段代码很熟悉,这是因为我们在上面使用了类似的代码render_my_option_1_field函数来获取我们字段的当前值。您也可以考虑为您的选项创建一个包装函数。示例:
// Helper function for returning theme options.
function myprefix_get_option( $option_name = '', $default = '' ) {
return get_option( 'my_options' )['my_option_1'] ?? $default;
}
// Usage.
$option_value = myprefix_get_option( 'my_option_1', 'default value' );
管理选项页面助手PHP类
下面的辅助类可以添加到您的主题或插件,可以用它来更方便得创建您的管理面板。建议将此代码放在您自己的文件中,并通过require_once
加载。
class WPEX_Options_Panel {
/**
* Options panel arguments.
*/
protected $args = [];
/**
* Options panel title.
*/
protected $title = '';
/**
* Options panel slug.
*/
protected $slug = '';
/**
* Option name to use for saving our options in the database.
*/
protected $option_name = '';
/**
* Option group name.
*/
protected $option_group_name = '';
/**
* User capability allowed to access the options page.
*/
protected $user_capability = '';
/**
* Our array of settings.
*/
protected $settings = [];
/**
* Our class constructor.
*/
public function __construct( array $args, array $settings ) {
$this->args = $args;
$this->settings = $settings;
$this->title = $this->args['title'] ?? esc_html__( 'Options', 'text_domain' );
$this->slug = $this->args['slug'] ?? sanitize_key( $this->title );
$this->option_name = $this->args['option_name'] ?? sanitize_key( $this->title );
$this->option_group_name = $this->option_name . '_group';
$this->user_capability = $args['user_capability'] ?? 'manage_options';
add_action( 'admin_menu', [ $this, 'register_menu_page' ] );
add_action( 'admin_init', [ $this, 'register_settings' ] );
}
/**
* Register the new menu page.
*/
public function register_menu_page() {
add_menu_page(
$this->title,
$this->title,
$this->user_capability,
$this->slug,
[ $this, 'render_options_page' ]
);
}
/**
* Register the settings.
*/
public function register_settings() {
register_setting( $this->option_group_name, $this->option_name, [
'sanitize_callback' => [ $this, 'sanitize_fields' ],
'default' => $this->get_defaults(),
] );
add_settings_section(
$this->option_name . '_sections',
false,
false,
$this->option_name
);
foreach ( $this->settings as $key => $args ) {
$type = $args['type'] ?? 'text';
$callback = "render_{$type}_field";
if ( method_exists( $this, $callback ) ) {
$tr_class = '';
if ( array_key_exists( 'tab', $args ) ) {
$tr_class .= 'wpex-tab-item wpex-tab-item--' . sanitize_html_class( $args['tab'] );
}
add_settings_field(
$key,
$args['label'],
[ $this, $callback ],
$this->option_name,
$this->option_name . '_sections',
[
'label_for' => $key,
'class' => $tr_class
]
);
}
}
}
/**
* Saves our fields.
*/
public function sanitize_fields( $value ) {
$value = (array) $value;
$new_value = [];
foreach ( $this->settings as $key => $args ) {
$field_type = $args['type'];
$new_option_value = $value[$key] ?? '';
if ( $new_option_value ) {
$sanitize_callback = $args['sanitize_callback'] ?? $this->get_sanitize_callback_by_type( $field_type );
$new_value[$key] = call_user_func( $sanitize_callback, $new_option_value, $args );
} elseif ( 'checkbox' === $field_type ) {
$new_value[$key] = 0;
}
}
return $new_value;
}
/**
* Returns sanitize callback based on field type.
*/
protected function get_sanitize_callback_by_type( $field_type ) {
switch ( $field_type ) {
case 'select':
return [ $this, 'sanitize_select_field' ];
break;
case 'textarea':
return 'wp_kses_post';
break;
case 'checkbox':
return [ $this, 'sanitize_checkbox_field' ];
break;
default:
case 'text':
return 'sanitize_text_field';
break;
}
}
/**
* Returns default values.
*/
protected function get_defaults() {
$defaults = [];
foreach ( $this->settings as $key => $args ) {
$defaults[$key] = $args['default'] ?? '';
}
return $defaults;
}
/**
* Sanitizes the checkbox field.
*/
protected function sanitize_checkbox_field( $value = '', $field_args = [] ) {
return ( 'on' === $value ) ? 1 : 0;
}
/**
* Sanitizes the select field.
*/
protected function sanitize_select_field( $value = '', $field_args = [] ) {
$choices = $field_args['choices'] ?? [];
if ( array_key_exists( $value, $choices ) ) {
return $value;
}
}
/**
* Renders the options page.
*/
public function render_options_page() {
if ( ! current_user_can( $this->user_capability ) ) {
return;
}
if ( isset( $_GET['settings-updated'] ) ) {
add_settings_error(
$this->option_name . '_mesages',
$this->option_name . '_message',
esc_html__( 'Settings Saved', 'text_domain' ),
'updated'
);
}
settings_errors( $this->option_name . '_mesages' );
?>
<div class="wrap">
<h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
<?php $this->render_tabs(); ?>
<form action="options.php" method="post" class="wpex-options-form">
<?php
settings_fields( $this->option_group_name );
do_settings_sections( $this->option_name );
submit_button( 'Save Settings' );
?>
</form>
</div>
<?php
}
/**
* Renders options page tabs.
*/
protected function render_tabs() {
if ( empty( $this->args['tabs'] ) ) {
return;
}
$tabs = $this->args['tabs'];
?>
<style>.wpex-tab-item{ display: none; ?></style>
<h2 class="nav-tab-wrapper wpex-tabs"><?php
$first_tab = true;
foreach ( $tabs as $id => $label ) {?>
<a href="#" data-tab="<?php echo esc_attr( $id ); ?>" class="nav-tab<?php echo ( $first_tab ) ? ' nav-tab-active' : ''; ?>"><?php echo ucfirst( $label ); ?></a>
<?php
$first_tab = false;
}
?></h2>
<script>
( function() {
document.addEventListener( 'click', ( event ) => {
const target = event.target;
if ( ! target.closest( '.wpex-tabs a' ) ) {
return;
}
event.preventDefault();
document.querySelectorAll( '.wpex-tabs a' ).forEach( ( tablink ) => {
tablink.classList.remove( 'nav-tab-active' );
} );
target.classList.add( 'nav-tab-active' );
targetTab = target.getAttribute( 'data-tab' );
document.querySelectorAll( '.wpex-options-form .wpex-tab-item' ).forEach( ( item ) => {
if ( item.classList.contains( `wpex-tab-item--${targetTab}` ) ) {
item.style.display = 'block';
} else {
item.style.display = 'none';
}
} );
} );
document.addEventListener( 'DOMContentLoaded', function () {
document.querySelector( '.wpex-tabs .nav-tab' ).click();
}, false );
} )();
</script>
<?php
}
/**
* Returns an option value.
*/
protected function get_option_value( $option_name ) {
$option = get_option( $this->option_name );
if ( ! array_key_exists( $option_name, $option ) ) {
return array_key_exists( 'default', $this->settings[$option_name] ) ? $this->settings[$option_name]['default'] : '';
}
return $option[$option_name];
}
/**
* Renders a text field.
*/
public function render_text_field( $args ) {
$option_name = $args['label_for'];
$value = $this->get_option_value( $option_name );
$description = $this->settings[$option_name]['description'] ?? '';
?>
<input
type="text"
id="<?php echo esc_attr( $args['label_for'] ); ?>"
name="<?php echo $this->option_name; ?>[<?php echo esc_attr( $args['label_for'] ); ?>]"
value="<?php echo esc_attr( $value ); ?>">
<?php if ( $description ) { ?>
<p class="description"><?php echo esc_html( $description ); ?></p>
<?php } ?>
<?php
}
/**
* Renders a textarea field.
*/
public function render_textarea_field( $args ) {
$option_name = $args['label_for'];
$value = $this->get_option_value( $option_name );
$description = $this->settings[$option_name]['description'] ?? '';
$rows = $this->settings[$option_name]['rows'] ?? '4';
$cols = $this->settings[$option_name]['cols'] ?? '50';
?>
<textarea
type="text"
id="<?php echo esc_attr( $args['label_for'] ); ?>"
rows="<?php echo esc_attr( absint( $rows ) ); ?>"
cols="<?php echo esc_attr( absint( $cols ) ); ?>"
name="<?php echo $this->option_name; ?>[<?php echo esc_attr( $args['label_for'] ); ?>]"><?php echo esc_attr( $value ); ?></textarea>
<?php if ( $description ) { ?>
<p class="description"><?php echo esc_html( $description ); ?></p>
<?php } ?>
<?php
}
/**
* Renders a checkbox field.
*/
public function render_checkbox_field( $args ) {
$option_name = $args['label_for'];
$value = $this->get_option_value( $option_name );
$description = $this->settings[$option_name]['description'] ?? '';
?>
<input
type="checkbox"
id="<?php echo esc_attr( $args['label_for'] ); ?>"
name="<?php echo $this->option_name; ?>[<?php echo esc_attr( $args['label_for'] ); ?>]"
<?php checked( $value, 1, true ); ?>
>
<?php if ( $description ) { ?>
<p class="description"><?php echo esc_html( $description ); ?></p>
<?php } ?>
<?php
}
/**
* Renders a select field.
*/
public function render_select_field( $args ) {
$option_name = $args['label_for'];
$value = $this->get_option_value( $option_name );
$description = $this->settings[$option_name]['description'] ?? '';
$choices = $this->settings[$option_name]['choices'] ?? [];
?>
<select
id="<?php echo esc_attr( $args['label_for'] ); ?>"
name="<?php echo $this->option_name; ?>[<?php echo esc_attr( $args['label_for'] ); ?>]"
>
<?php foreach ( $choices as $choice_v => $label ) { ?>
<option value="<?php echo esc_attr( $choice_v ); ?>" <?php selected( $choice_v, $value, true ); ?>><?php echo esc_html( $label ); ?></option>
<?php } ?>
</select>
<?php if ( $description ) { ?>
<p class="description"><?php echo esc_html( $description ); ?></p>
<?php } ?>
<?php
}
}
使用示例
示例一
// Register new Options panel.
$panel_args = [
'title' => 'My Options',
'option_name' => 'my_options',
'slug' => 'my-options-panel',
'user_capability' => 'manage_options',
];
$panel_settings = [
'option_1' => [
'label' => esc_html__( 'Checkbox Option', 'text_domain' ),
'type' => 'checkbox',
'description' => 'My checkbox field description.',
],
'option_2' => [
'label' => esc_html__( 'Select Option', 'text_domain' ),
'type' => 'select',
'description' => 'My select field description.',
'choices' => [
'' => esc_html__( 'Select', 'text_domain' ),
'choice_1' => esc_html__( 'Choice 1', 'text_domain' ),
'choice_2' => esc_html__( 'Choice 2', 'text_domain' ),
'choice_3' => esc_html__( 'Choice 3', 'text_domain' ),
],
],
'option_3' => [
'label' => esc_html__( 'Text Option', 'text_domain' ),
'type' => 'text',
'description' => 'My field 1 description.',
],
'option_4' => [
'label' => esc_html__( 'Textarea Option', 'text_domain' ),
'type' => 'textarea',
'description' => 'My textarea field description.',
],
];
new WPEX_Options_Panel( $panel_args, $panel_settings );
示例二
// Register new Options panel.
$panel_args = [
'title' => 'My Options',
'option_name' => 'my_options',
'slug' => 'my-options-panel',
'user_capability' => 'manage_options',
'tabs' => [
'tab-1' => esc_html__( 'Tab 1', 'text_domain' ),
'tab-2' => esc_html__( 'Tab 2', 'text_domain' ),
],
];
$panel_settings = [
// Tab 1
'option_1' => [
'label' => esc_html__( 'Checkbox Option', 'text_domain' ),
'type' => 'checkbox',
'description' => 'My checkbox field description.',
'tab' => 'tab-1',
],
'option_2' => [
'label' => esc_html__( 'Select Option', 'text_domain' ),
'type' => 'select',
'description' => 'My select field description.',
'choices' => [
'' => esc_html__( 'Select', 'text_domain' ),
'choice_1' => esc_html__( 'Choice 1', 'text_domain' ),
'choice_2' => esc_html__( 'Choice 2', 'text_domain' ),
'choice_3' => esc_html__( 'Choice 3', 'text_domain' ),
],
'tab' => 'tab-1',
],
// Tab 2
'option_3' => [
'label' => esc_html__( 'Text Option', 'text_domain' ),
'type' => 'text',
'description' => 'My field 1 description.',
'tab' => 'tab-2',
],
'option_4' => [
'label' => esc_html__( 'Textarea Option', 'text_domain' ),
'type' => 'textarea',
'description' => 'My textarea field description.',
'tab' => 'tab-2',
],
];
new WPEX_Options_Panel( $panel_args, $panel_settings );
本文系转载,作者为AJ Clarke,以下是原文链接:
https://www.wpexplorer.com/wordpress-theme-options/