WordPress Settings API: Реализация вкладок на пользовательской странице меню
Я изучал серию уроков по WordPress Settings API этого автора:
Базовые элементы настроек были реализованы успешно, однако при добавлении системы вкладок возникли следующие проблемы:
Проблема 1: Некорректная работа вкладок. Все поля отображаются одновременно на обеих вкладках. Раздел 1 должен быть виден только на первой вкладке, Раздел 2 - на второй.
Проблема 2: Опция 2 не сохраняет значения. До внедрения системы вкладок функциональность работала корректно.
/* ----------------------------------------------------------------------------- */
/* Добавление страницы меню */
/* ----------------------------------------------------------------------------- */
function add_my_menu() {
add_menu_page(
'Заголовок страницы', // Заголовок страницы в админке
'Заголовок меню', // Название пункта меню
'manage_options', // Требуемые права доступа
'my-menu-slug', // Уникальный ярлык меню
'my_menu_page', // Функция отображения контента
get_template_directory_uri() . '/assets/ico/theme-option-menu-icon.png', // Иконка меню
// $position // Позиция в меню (не используется)
);
}
add_action('admin_menu', 'add_my_menu');
function my_menu_page() {
?>
<div class="wrap">
<?php
// Определение активной вкладки
$active_tab = isset($_GET['tab']) ? $_GET['tab'] : 'tab_one';
?>
<h2>Заголовок страницы настроек</h2>
<div class="description">Описание функционала страницы</div>
<?php settings_errors(); ?>
<!-- Навигационные вкладки -->
<h2 class="nav-tab-wrapper">
<a href="?page=my-menu-slug&tab=tab_one" class="nav-tab <?php echo $active_tab == 'tab_one' ? 'nav-tab-active' : ''; ?>">
Вкладка 1
</a>
<a href="?page=my-menu-slug&tab=tab_two" class="nav-tab <?php echo $active_tab == 'tab_two' ? 'nav-tab-active' : ''; ?>">
Вкладка 2
</a>
</h2>
<form method="post" action="options.php">
<?php
if ($active_tab == 'tab_one') {
settings_fields('setting-group-1');
do_settings_sections('my-menu-slug');
} elseif ($active_tab == 'tab_two') {
settings_fields('setting-group-2');
do_settings_sections('my-menu-slug');
}
submit_button();
?>
</form>
</div>
<?php
}
/* ----------------------------------------------------------------------------- */
/* Регистрация секций и полей */
/* ----------------------------------------------------------------------------- */
function sandbox_initialize_theme_options() {
// Секция 1
add_settings_section(
'page_1_section', // Уникальный идентификатор секции
'Раздел 1', // Заголовок секции
'page_1_section_callback', // Функция вывода описания
'my-menu-slug' // Страница отображения
);
// Секция 2
add_settings_section(
'page_2_section',
'Раздел 2',
'page_2_section_callback',
'my-menu-slug'
);
/* ------------------------- */
/* Поле опции 1 */
/* ------------------------- */
add_settings_field(
'option_1', // Идентификатор опции
'Опция 1', // Название поля
'option_1_callback', // Callback функция
'my-menu-slug', // Страница
'page_1_section', // Секция
array( // Аргументы
'Детальное описание функционала опции 1'
)
);
register_setting('setting-group-1', 'option_1');
/* ------------------------- */
/* Поле опции 2 */
/* ------------------------- */
add_settings_field(
'option_2',
'Опция 2',
'option_2_callback',
'my-menu-slug',
'page_2_section',
array(
'Детальное описание функционала опции 2'
)
);
register_setting('setting-group-2', 'option_2');
}
add_action('admin_init', 'sandbox_initialize_theme_options');
/* ----------------------------------------------------------------------------- */
/* Колбэк-функции секций */
/* ----------------------------------------------------------------------------- */
function page_1_section_callback() {
echo '<p>Дополнительное описание раздела настроек</p>';
}
function page_2_section_callback() {
echo '<p>Дополнительное описание раздела настроек</p>';
}
/* ----------------------------------------------------------------------------- */
/* Колбэк-функции полей */
/* ----------------------------------------------------------------------------- */
function option_1_callback($args) {
?>
<input type="text"
id="option_1"
name="option_1"
value="<?php echo esc_attr(get_option('option_1')); ?>"
class="regular-text">
<p class="description"><?php echo $args[0]; ?></p>
<?php
}
function option_2_callback($args) {
?>
<textarea id="option_2"
name="option_2"
rows="5"
cols="50"
class="large-text code"><?php echo esc_textarea(get_option('option_2')); ?></textarea>
<p class="description"><?php echo $args[0]; ?></p>
<?php
}

Вот как я это делаю, предупреждаю, пост объемный.
/* Добавление меню
-----------------------------------------------------------------*/
add_action('admin_menu', 'ch_essentials_admin');
function ch_essentials_admin() {
/* Основное меню */
add_menu_page(
'Тема Essentials',
'Тема Essentials',
'manage_options',
'ch-essentials-options',
'ch_essentials_index');
}
Теперь настройки полей, лишние поля удалены, просто как пример.
Это для 'Настроек Главной Страницы' и 'Вкладки Главной Страницы'
add_action('admin_init', 'ch_essentials_options');
function ch_essentials_options() {
/* Секция настроек главной страницы */
add_settings_section(
'ch_essentials_front_page',
'Настройки главной страницы Essentials',
'ch_essentials_front_page_callback',
'ch_essentials_front_page_option'
);
add_settings_field(
'featured_post',
'Избранный пост',
'ch_essentials_featured_post_callback',
'ch_essentials_front_page_option',
'ch_essentials_front_page'
);
Это для настроек заголовка, вкладка 'Настройки заголовка'
/* Секция настроек заголовка */
add_settings_section(
'ch_essentials_header',
'Настройки заголовка Essentials',
'ch_essentials_header_callback',
'ch_essentials_header_option'
);
add_settings_field(
'header_type',
'Тип заголовка',
'ch_essentials_textbox_callback',
'ch_essentials_header_option',
'ch_essentials_header',
array(
'header_type'
)
);
Регистрация настроек
register_setting('ch_essentials_front_page_option', 'ch_essentials_front_page_option');
register_setting('ch_essentials_header_option', 'ch_essentials_header_option');
Всё это обернуто в одну функцию, затем выполняется через admin_init
/* Настройки
-----------------------------------------------------------------*/
add_action('admin_init', 'ch_essentials_options');
function ch_essentials_options() {
/* Код показан выше */
}
Функции обратного вызова:
/* Функции обратного вызова
-----------------------------------------------------------------*/
function ch_essentials_front_page_callback() {
echo '<p>Настройки отображения главной страницы:</p>';
}
function ch_essentials_header_callback() {
echo '<p>Настройки отображения заголовка:</p>';
}
function ch_essentials_textbox_callback($args) {
$options = get_option('ch_essentials_header_option');
echo '<input type="text" id="' . $args[0] . '" name="ch_essentials_header_option[' . $args[0] . ']" value="' . $options['' . $args[0] . ''] . '"></input>';
}
function ch_essentials_featured_post_callback($args) {
$options = get_option('ch_essentials_front_page_option');
query_posts( $args );
echo '<select id="featured_post" name="ch_essentials_front_page_option[featured_post]">';
while ( have_posts() ) : the_post();
$selected = selected($options['featured_post'], get_the_id(), false);
printf('<option value="%s" %s>%s</option>', get_the_id(), $selected, get_the_title());
endwhile;
echo '</select>';
}
Теперь часть отображения, с вкладками..
Если ваши секции и поля настроек сделаны точно так же, то вы сможете реализовать вкладки без проблем.
/* Страница отображения
-----------------------------------------------------------------*/
function ch_essentials_index() {
?>
<div class="wrap">
<div id="icon-themes" class="icon32"></div>
<h2>Настройки темы Essentials</h2>
<?php settings_errors(); ?>
<?php
$active_tab = isset( $_GET[ 'tab' ] ) ? $_GET[ 'tab' ] : 'front_page_options';
?>
<h2 class="nav-tab-wrapper">
<a href="?page=ch-essentials-options&tab=front_page_options" class="nav-tab <?php echo $active_tab == 'front_page_options' ? 'nav-tab-active' : ''; ?>">Настройки главной страницы</a>
<a href="?page=ch-essentials-options&tab=header_options" class="nav-tab <?php echo $active_tab == 'header_options' ? 'nav-tab-active' : ''; ?>">Настройки заголовка</a>
</h2>
<form method="post" action="options.php">
<?php
if( $active_tab == 'front_page_options' ) {
settings_fields( 'ch_essentials_front_page_option' );
do_settings_sections( 'ch_essentials_front_page_option' );
} else if( $active_tab == 'header_options' ) {
settings_fields( 'ch_essentials_header_option' );
do_settings_sections( 'ch_essentials_header_option' );
}
?>
<?php submit_button(); ?>
</form>
</div>
<?php
}
-----ИЗМЕНЕНО-----
и я заметил в вашем посте, что у вас используется 'elseif' вместо 'else if' на реальной странице отображения в разделе вкладок

Это было весьма полезно для меня. У меня были трудности с преобразованием одной страницы в страницу с вкладками. Единственное, что я добавил - проверку empty() для массива $option для каждого поля ввода. В противном случае я получал ошибку, когда значение не было установлено. Я также добавил третий аргумент в register_settings(). Он принимает опциональный массив для настройки таких вещей, как санитизация. В целом, это был очень хороший пост с качественным кодом.

Вот как это сработало у меня:
<?php
/* ----------------------------------------------------------------------------- */
/* Добавление страницы меню */
/* ----------------------------------------------------------------------------- */
function add_my_menu() {
add_menu_page (
'Заголовок страницы', // заголовок страницы
'Заголовок меню', // заголовок меню
'manage_options', // права доступа
'my-menu-slug', // ярлык меню
'my_menu_page', // функция, которая будет выводить контент
get_template_directory_uri() . '/assets/ico/theme-option-menu-icon.png' // ссылка на иконку, которая будет отображаться в сайдбаре
//$position, // позиция пункта меню
);
}
add_action('admin_menu', 'add_my_menu');
function my_menu_page() {
?>
<?php
if( isset( $_GET[ 'tab' ] ) ) {
$active_tab = $_GET[ 'tab' ];
} else {
$active_tab = 'tab_one';
}
?>
<div class="wrap">
<h2>Заголовок страницы меню</h2>
<div class="description">Это описание страницы.</div>
<?php settings_errors(); ?>
<h2 class="nav-tab-wrapper">
<a href="?page=my-menu-slug&tab=tab_one" class="nav-tab <?php echo $active_tab == 'tab_one' ? 'nav-tab-active' : ''; ?>">Вкладка 1</a>
<a href="?page=my-menu-slug&tab=tab_two" class="nav-tab <?php echo $active_tab == 'tab_two' ? 'nav-tab-active' : ''; ?>">Вкладка 2</a>
</h2>
<form method="post" action="options.php">
<?php
if( $active_tab == 'tab_one' ) {
settings_fields( 'setting-group-1' );
do_settings_sections( 'my-menu-slug-1' );
} else if( $active_tab == 'tab_two' ) {
settings_fields( 'setting-group-2' );
do_settings_sections( 'my-menu-slug-2' );
}
?>
<?php submit_button(); ?>
</form>
</div>
<?php
}
/* ----------------------------------------------------------------------------- */
/* Настройка секций и полей */
/* ----------------------------------------------------------------------------- */
function sandbox_initialize_theme_options() {
add_settings_section(
'page_1_section', // ID секции
'Секция 1', // Название секции
'page_1_section_callback', // Функция для вывода описания секции
'my-menu-slug-1' // Страница, на которой будет отображаться секция
);
add_settings_section(
'page_2_section', // ID секции
'Секция 2', // Название секции
'page_2_section_callback', // Функция для вывода описания секции
'my-menu-slug-2' // Страница, на которой будет отображаться секция
);
/* ----------------------------------------------------------------------------- */
/* Опция 1 */
/* ----------------------------------------------------------------------------- */
add_settings_field (
'option_1', // ID поля
'Опция 1', // Название поля
'option_1_callback', // Функция для вывода поля
'my-menu-slug-1', // Страница, на которой будет отображаться поле
'page_1_section', // ID секции
array( // Аргументы для callback-функции
'Это описание опции 1',
)
);
register_setting(
'setting-group-1',
'option_1'
);
/* ----------------------------------------------------------------------------- */
/* Опция 2 */
/* ----------------------------------------------------------------------------- */
add_settings_field (
'option_2', // ID поля
'Опция 2', // Название поля
'option_2_callback', // Функция для вывода поля
'my-menu-slug-2', // Страница, на которой будет отображаться поле
'page_2_section', // ID секции
array(
'Это описание опции 2', // Описание поля.
)
);
register_setting(
'setting-group-2',
'option_2'
);
} // function sandbox_initialize_theme_options
add_action('admin_init', 'sandbox_initialize_theme_options');
function page_1_section_callback() {
echo '<p>Описание секции здесь</p>';
} // function page_1_section_callback
function page_2_section_callback() {
echo '<p>Описание секции здесь</p>';
} // function page_1_section_callback
/* ----------------------------------------------------------------------------- */
/* Функции вывода полей */
/* ----------------------------------------------------------------------------- */
function option_1_callback($args) {
?>
<input type="text" id="option_1" class="option_1" name="option_1" value="<?php echo get_option('option_1') ?>">
<p class="description option_1"> <?php echo $args[0] ?> </p>
<?php
} // end sandbox_toggle_header_callback
function option_2_callback($args) {
?>
<textarea id="option_2" class="option_2" name="option_2" rows="5" cols="50"><?php echo get_option('option_2') ?></textarea>
<p class="description option_2"> <?php echo $args[0] ?> </p>
<?php
} // end sandbox_toggle_header_callback
?>

<form method="post" action="options.php">
<?php
if( $active_tab == 'tab_one' ) {
settings_fields( 'setting-group-1' );
do_settings_sections( 'my-menu-slug-1' );
} elseif( $active_tab == 'tab_two' ) {
settings_fields( 'setting-group-2' );
do_settings_sections( 'my-menu-slug-1' );
}
?>
Измените my-menu-slug
на my-menu-slug-1
и my-menu-slug-2
