WordPress Settings API: Реализация вкладок на пользовательской странице меню

23 дек. 2013 г., 23:09:51
Просмотры: 17.5K
Голосов: 10

Я изучал серию уроков по WordPress Settings API этого автора:

http://wp.tutsplus.com/tutorials/theme-development/the-complete-guide-to-the-wordpress-settings-api-part-1/

Базовые элементы настроек были реализованы успешно, однако при добавлении системы вкладок возникли следующие проблемы:

Проблема 1: Некорректная работа вкладок. Все поля отображаются одновременно на обеих вкладках. Раздел 1 должен быть виден только на первой вкладке, Раздел 2 - на второй.

Проблема 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
}
2
Комментарии

Я не слишком хорошо знаком с API настроек, но на первый взгляд кажется, что все ваши поля относятся к одному разделу настроек, который вы выводите в обеих вкладках.

Milo Milo
23 дек. 2013 г. 23:20:13

@Milo У меня получилось заставить это работать, но я бы сказал, что WordPress Settings API очень сложен для понимания. Также у него практически отсутствует официальная документация.

Omar Tariq Omar Tariq
24 дек. 2013 г. 10:18:49
Все ответы на вопрос 3
2
16

Вот как я это делаю, предупреждаю, пост объемный.

/* Добавление меню
-----------------------------------------------------------------*/
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' на реальной странице отображения в разделе вкладок

24 дек. 2013 г. 02:04:50
Комментарии

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

benjaminadk benjaminadk
10 мар. 2020 г. 06:43:49

почему слово 'options' во множественном числе в шаблоне, но в единственном числе в add_settings_field?

Philip Philip
25 сент. 2023 г. 02:35:45
0

Вот как это сработало у меня:

<?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  

?>
11 нояб. 2016 г. 14:35:30
0
<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

12 мар. 2015 г. 10:08:42