Статьи

Использование API настроек: Часть 1. Страница «Создание темы»

Если вы создаете свои собственные темы, вы, рано или поздно, захотите позволить пользователям вашей темы иметь некоторый контроль над определенным внешним видом и / или функциональными элементами вашей темы. Когда это время придет, вы захотите использовать мощный API настроек WordPress. Благодаря этому ваш код становится проще, эффективнее и безопаснее.

Этот учебник не первый, в котором используется API настроек для создания страницы настроек темы или плагина. На самом деле в сообществе WordPress уже доступно большое количество учебников. Некоторые качественные учебные пособия включают в себя учебник по расширенным API настроек WordPress (из двух частей) от Элисон Барретт, а также хорошо известное включение API настроек в темы WordPress Чипа Беннетта.

Это руководство основано на некоторых превосходных методах кода, которые можно найти в этих руководствах (заслуга обоих!), Поэтому, если вы не знакомы с ними, я определенно рекомендую вам прочитать эти две статьи. Я надеюсь, что в этом руководстве вы найдете код, который вы сможете использовать и улучшить в своей работе. Прямо тогда! Давайте прямо к этому!


Я думаю, что всегда приятно, когда начинаются уроки, показывающие, как выглядит готовый результат. Так почему бы нам не начать с этого? В этом уроке мы будем использовать тему WordPress 3.2 по умолчанию twentyeleven, однако вы можете использовать свою собственную тему, если хотите.

  1. Загрузите исходные файлы и разархивируйте
  2. Найдите папку Part One/source_files/lib и загрузите ее в папку темы twentyeleven, чтобы она находилась на том же уровне, что и twentyeleven/js вы видите.
  3. Затем откройте Part One/source_files/functions.php в редакторе кода и скопируйте строку кода require_once .
  4. Затем откройте twentyeleven/functions.php в вашем редакторе кода. Найдите twentyeleven_setup() вокруг строки 74 и вставьте строку, которую вы скопировали ранее (точка 3), внутри функции, как показано ниже.
1
2
3
4
5
6
function twentyeleven_setup() {
 
    //require only in admin!
    if(is_admin()){
        require_once(‘lib/wptuts-theme-settings-basic.php’);
    }

После выполнения этого шага вы сможете увидеть ссылку «Параметры Wptuts» в меню верхнего уровня « Внешний вид» WordPress в вашей области администратора. Перейдите к нему и найдите время, чтобы просмотреть содержимое страницы. За заголовком страницы настроек Wptuts находятся четыре раздела настроек с отдельными полями настроек:

  • Поля текстовой формы
  • Поля формы текстовой области
  • Выберите поля формы
  • Поля формы флажка

Обратите внимание, что некоторые настройки позволяют использовать теги HTML, а другие — нет Некоторые настройки предназначены только для числового ввода. Попробуйте сохранить настройки по умолчанию и увидеть «Настройки сохранены». появится сообщение администратора Попробуйте сохранить ввод с тегами HTML в настройках, которые не позволяют их использовать, и посмотрите, как они удалены. Теперь перейдите к настройке ввода электронной почты и сохраните неправильный формат электронной почты, такой как email @ email. Сохраните настройки и увидите сообщение об ошибке администратора. Посмотрите также, как параметр, который необходимо исправить, выделен красным, чтобы мы точно знали, куда идти и что исправлять.

Теперь, когда вы видите, как выглядит готовый результат, давайте узнаем, как мы можем воссоздать его шаг за шагом.


«Окончательный код, описанный в этом шаге, находится в папке Part One/source_ files/step1 »

Этот шаг о создании пустой страницы, которая в конечном итоге будет отображать наши настройки. Поскольку первая часть этого руководства требует только одной страницы настроек, мы просто добавим подменю в существующее меню верхнего уровня Appearance . ( Во второй части будет показано, как добавлять вкладки, а также более одной страницы настроек.) Мы вызовем add_theme_page() в нашей собственной функции wptuts_add_menu() и подключим ее к admin_menu действий admin_menu .

Создайте новый документ в редакторе кода и назовите его my-theme-settings.php Сохраните его и загрузите в twentyeleven/lib . Откройте twentyeleven/functions.php в редакторе кода и найдите строку кода require_once вы вставили ранее, и отредактируйте имя файла, чтобы отразить имя нового документа, который вы только что создали.

Код, приведенный ниже, должен быть записан в twentyeleven/functions.php .

1
2
3
4
5
6
function twentyeleven_setup() {
 
    //require only in admin!
    if(is_admin()){
        require_once(‘lib/my-theme-settings.php’);
    }

Сначала мы определим некоторые константы. Это немного облегчит, когда вы захотите позже настроить код под свои нужды.

Весь приведенный ниже код и оставшаяся часть шага 1 должны быть записаны в файле my-theme-settings.php .

1
2
3
4
5
/*
 * Define Constants
 */
define(‘WPTUTS_SHORTNAME’, ‘wptuts’);
define(‘WPTUTS_PAGE_BASENAME’, ‘wptuts-settings’);

Далее скажите WordPress, что мы хотим зарегистрировать страницу настроек. Для этого нам нужно написать функцию и подключить ее к admin_menu действий admin_menu .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
/*
 * Specify Hooks/Filters
 */
add_action( ‘admin_menu’, ‘wptuts_add_menu’ );
 
/*
 * The Admin menu page
 */
function wptuts_add_menu(){
     
    // Display Settings Page link under the «Appearance» Admin Menu
    // add_theme_page( $page_title, $menu_title, $capability, $menu_slug, $function);
    $wptuts_settings_page = add_theme_page(__(‘Wptuts Options’), __(‘Wptuts Options’,’wptuts_textdomain’), ‘manage_options’, WPTUTS_PAGE_BASENAME, ‘wptuts_settings_page_fn’);
}

Поймите параметры add_theme_page()

add_theme_page() параметры функции add_theme_page() чтобы позже вы могли настроить вызов функции в соответствии с вашими потребностями. Информация взята со страницы Кодекса :

  • $page_title — текст, отображаемый в тегах заголовка страницы при $page_title меню
  • $menu_title — текст, который будет использоваться для меню
  • $capability — Возможность, необходимая для отображения этого меню пользователю.
  • $menu_slug — имя пули, к $menu_slug относится это меню (должно быть уникальным для этого меню). (Обратите внимание на использование нашей константы WPTUTS_PAGE_BASENAME !)
  • $function$function обратного вызова для вывода содержимого этой страницы. ( wptuts_settings_page_fn() описана ниже.)

Пятый параметр в add_theme_page() — т.е. wptuts_settings_page_fn() — отвечает за отображение содержимого нашей страницы. Однако, прежде чем мы напишем его, нам нужно определить вспомогательную функцию, которая поможет собрать вместе окончательный вывод страницы (заголовок страницы, разделы настроек, поля настроек и контекстную справку). Скопируйте и вставьте код, который вы видите ниже после вызова admin_menu действия admin_menu .

Вспомогательная функция

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
/**
 * Helper function for defining variables for the current page
 *
 * @return array
 */
function wptuts_get_settings() {
     
    $output = array();
     
    // put together the output array
    $output[‘wptuts_option_name’] = »;
    $output[‘wptuts_page_title’] = __( ‘Wptuts Settings Page’,’wptuts_textdomain’);
    $output[‘wptuts_page_sections’] = »;
    $output[‘wptuts_page_fields’] = »;
    $output[‘wptuts_contextual_help’] = »;
     
return $output;
}

Вспомогательная функция wptuts_get_settings() выводит ассоциативный массив со следующими значениями (в порядке их записи):

  • Имя опции, которое мы будем использовать в get_option() . (см. шаг 2)
  • Заголовок страницы настроек. (см. ниже)
  • Разделы настроек. (см. шаг 3)
  • Поля настроек (настройки). (см. шаг 4)
  • Настройки контекстная помощь. (см. шаг 7)

Функция вывода контента страницы

Скопируйте и вставьте код, который вы видите ниже, после функции wptuts_get_settings() .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
/*
 * Admin Settings Page HTML
 *
 * @return echoes output
 */
function wptuts_settings_page_fn() {
// get the settings sections array
    $settings_output = wptuts_get_settings();
?>
    <div class=»wrap»>
        <div class=»icon32″ id=»icon-options-general»></div>
        <h2><?php echo $settings_output[‘wptuts_page_title’];
         
        <form action=»options.php» method=»post»>
            <p class=»submit»>
                <input name=»Submit» type=»submit» class=»button-primary» value=»<?php esc_attr_e(‘Save Changes’,’wptuts_textdomain’); ?>» />
            </p>
             
        </form>
    </div><!— wrap —>
<?php }

Если вы успешно выполнили все вышеперечисленное, вот так должна выглядеть ваша страница настроек на этом этапе.


«Окончательный код, описанный в этом шаге, находится в папке Part One/source_ files/step2 »

Теперь, когда у нас есть страница настроек, нам нужно сообщить WordPress настройки, которые мы хотим зарегистрировать, и внести их в белый список, т. Е. Выполнить санитарную обработку. Этот шаг как раз об этом. Это не изменит внешний вид нашей страницы, поэтому не ожидайте «увидеть» отраженные изменения. Вся эта жизненно важная работа выполняется в фоновом режиме. Мы будем использовать функцию register_setting() и ее санитарный обратный вызов в нашей пользовательской функции wptuts_register_settings() а затем перехватим это на admin_init действия admin_init . Однако прежде чем сделать это, нам нужно настроить нашу вспомогательную wptuts_get_settings() чтобы она включала значение для $output['wptuts_option_name'] .

Код, приведенный ниже, должен быть записан в файле my-theme-settings.php .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
/**
 * Helper function for defining variables for the current page
 *
 * @return array
 */
function wptuts_get_settings() {
     
    $output = array();
     
    // put together the output array
    $output[‘wptuts_option_name’] = ‘wptuts_options’;
    $output[‘wptuts_page_title’] = __( ‘Wptuts Settings Page’,’wptuts_textdomain’);
    $output[‘wptuts_page_sections’] = »;
    $output[‘wptuts_page_fields’] = »;
    $output[‘wptuts_contextual_help’] = »;
     
return $output;
}

Теперь добавьте следующий блок кода чуть ниже функции wptuts_get_settings() .

01
02
03
04
05
06
07
08
09
10
11
12
13
/*
 * Register our setting
 */
function wptuts_register_settings(){
     
    // get the settings sections array
    $settings_output = wptuts_get_settings();
    $wptuts_option_name = $settings_output[‘wptuts_option_name’];
     
    //setting
    //register_setting( $option_group, $option_name, $sanitize_callback );
    register_setting($wptuts_option_name, $wptuts_option_name, ‘wptuts_validate_options’ );
}

Добавьте это крюк.

1
2
3
4
5
/*
 * Specify Hooks/Filters
 */
add_action( ‘admin_menu’, ‘wptuts_add_menu’ );
add_action( ‘admin_init’, ‘wptuts_register_settings’ );

Понять параметры register_setting()

Обратите внимание на параметры функции register_setting() . Информация взята со страницы Кодекса :

  • $option_group — имя группы настроек. (Для простоты мы назовем его так же, как параметр $option_name ниже)
  • $option_name — имя опции для очистки и сохранения. (что мы используем в get_option() .)
  • $sanitize_callback — функция обратного вызова, которая очищает значение параметра.

Наконец, для этого шага мы хотим определить нашу wptuts_validate_options() обратного вызова проверки wptuts_validate_options() . Это еще ничего не сделает. Тем не менее, хорошо подготовить его и подготовить к шагу 6. ​​Скопируйте и вставьте приведенный ниже код в конец нашего документа и перед закрывающим тегом php.

01
02
03
04
05
06
07
08
09
10
11
12
/*
 * Validate input
 *
 * @return array
 */
function wptuts_validate_options($input) {
     
    // for enhanced security, create a new empty array
    $valid_input = array();
     
return $valid_input;
}

Если вы успешно выполнили вышесказанное, ваша страница настроек должна выглядеть так же, как в конце шага 1!


«Окончательный код, описанный в этом шаге, находится в папке Part One/source_ files/step3 »

Этот шаг охватывает четыре раздела настроек, которые нам понадобятся. Часть кода, которую мы рассмотрим, нужно будет написать в отдельном файле, который мы включим в наш my-theme-settings.php так что давайте начнем с этого.

Создайте новый документ в своем редакторе кода и назовите его my-theme-options.php Скопируйте и вставьте в него функцию, которую вы видите ниже. Затем сохраните документ и загрузите его в twentyeleven/lib .

Код, приведенный ниже, должен быть записан в файле my-theme-options.php .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
/**
 * Define our settings sections
 *
 * array key=$id, array value=$title in: add_settings_section( $id, $title, $callback, $page );
 * @return array
 */
function wptuts_options_page_sections() {
     
    $sections = array();
    // $sections[$id] = __($title, ‘wptuts_textdomain’);
    $sections[‘txt_section’] = __(‘Text Form Fields’, ‘wptuts_textdomain’);
    $sections[‘txtarea_section’] = __(‘Textarea Form Fields’, ‘wptuts_textdomain’);
    $sections[‘select_section’] = __(‘Select Form Fields’, ‘wptuts_textdomain’);
    $sections[‘checkbox_section’] = __(‘Checkbox Form Fields’, ‘wptuts_textdomain’);
     
    return $sections;
}

Функция wptuts_options_page_sections() определяет наши разделы настроек. Он выводит ассоциативный массив. Значение массива обозначает заголовок раздела, а ключ массива — идентификатор раздела.
Оба необходимы для add_settings_section() вызова функции add_settings_section() .

Мы хотим иметь возможность использовать то, что wptuts_options_page_sections() возвращает в файле my-theme-settings.php . Убедитесь, что вы включили my-theme-options.php как показано ниже. Код добавляется после вызова admin_menu действия admin_menu .

Код, приведенный ниже, и оставшаяся часть шага 3 должны быть записаны в файле my-theme-settings.php .

1
2
3
4
5
/*
 * Include the required files
 */
// page settings sections & fields
require_once(‘my-theme-options.php’);

Затем мы настраиваем вспомогательную функцию wptuts_get_settings() чтобы включить значение для переменной $output['wptuts_page_sections'] .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
/**
 * Helper function for defining variables for the current page
 *
 * @return array
 */
function wptuts_get_settings() {
     
    $output = array();
     
    // put together the output array
    $output[‘wptuts_option_name’] = ‘wptuts_options’;
    $output[‘wptuts_page_title’] = __( ‘Wptuts Settings Page’,’wptuts_textdomain’);
    $output[‘wptuts_page_sections’] = wptuts_options_page_sections();
    $output[‘wptuts_page_fields’] = »;
    $output[‘wptuts_contextual_help’] = »;
     
return $output;
}

Теперь давайте зарегистрируем наши разделы настроек, вызвав add_settings_section() . Помните, что разделы настроек, которые мы определили, хранятся в виде массива, поэтому нам нужно запустить цикл foreach .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
/*
 * Register our setting
 */
function wptuts_register_settings(){
     
    // get the settings sections array
    $settings_output = wptuts_get_settings();
    $wptuts_option_name = $settings_output[‘wptuts_option_name’];
     
    //setting
    // register_setting( $option_group, $option_name, $sanitize_callback );
    register_setting($wptuts_option_name, $wptuts_option_name, ‘wptuts_validate_options’ );
     
    //sections
    // add_settings_section( $id, $title, $callback, $page );
    if(!empty($settings_output[‘wptuts_page_sections’])){
        // call the «add_settings_section» for each!
        foreach ( $settings_output[‘wptuts_page_sections’] as $id => $title ) {
            add_settings_section( $id, $title, ‘wptuts_section_fn’, __FILE__);
        }
    }
}

Понять параметры register_setting()

Обратите внимание на параметры функции add_settings_section() . Информация взята со страницы Кодекса :

  • $id — Строка для использования в атрибуте ‘id’ тегов. (Ключ массива в нашем массиве $section .)
  • $title — Название раздела. (Значение массива в нашем массиве $section .)
  • $callback — имя функции обратного вызова, которая повторяет некоторые пояснения об этом разделе. (Функция wptuts_section_fn() определена ниже.)
  • $page$page настроек для отображения раздела.

Функция обратного вызова разделов настроек — т.е. wptuts_section_fn() — будет wptuts_section_fn() его содержимое для каждого раздела, который мы создали.

1
2
3
4
5
6
7
/*
 * Section HTML, displayed before the first option
 * @return echoes output
 */
function wptuts_section_fn($desc) {
    echo «<p>» .
}

Наконец, мы сообщаем WordPress, что хотим, чтобы разделы отображались на нашей странице настроек. Мы делаем это, вызывая 2 функции: settings_fields() и do_settings_sections() в нашем wptuts_settings_page_fn( )

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*
 * Admin Settings Page HTML
 *
 * @return echoes output
 */
function wptuts_settings_page_fn() {
// get the settings sections array
    $settings_output = wptuts_get_settings();
?>
    <div class=»wrap»>
        <div class=»icon32″ id=»icon-options-general»></div>
        <h2><?php echo $settings_output[‘wptuts_page_title’];
         
        <form action=»options.php» method=»post»>
            <?php
            // http://codex.wordpress.org/Function_Reference/settings_fields
            settings_fields($settings_output[‘wptuts_option_name’]);
             
            // http://codex.wordpress.org/Function_Reference/do_settings_sections
            do_settings_sections(__FILE__);
            ?>
            <p class=»submit»>
                <input name=»Submit» type=»submit» class=»button-primary» value=»<?php esc_attr_e(‘Save Changes’,’wptuts_textdomain’); ?>» />
            </p>
             
        </form>
    </div><!— wrap —>
<?php }

Если вы успешно выполнили все вышеперечисленное, вот так должна выглядеть ваша страница настроек на этом этапе.


«Окончательный код, описанный на этом шаге, находится в Part One/source_ files/step4/ my-theme-settings.php »

Этот шаг все о реальных настройках или, как они называются в настройках API , поля настроек. Мы начнем с определения новой вспомогательной функции.

Функция (написанная Элисон Барретт) объясняется в ее собственном уроке
поэтому я бы посоветовал вам прочитать это в какой-то момент. Пожалуйста, обратите внимание на тот факт, что наша wptuts_create_settings_field() будет передавать аргумент $class в нашу функцию проверки, поэтому его нет просто для стилистического использования в файле CSS!

Приведенный ниже код должен быть записан в файл my-theme-settings.php сразу после функции wptuts_get_settings() .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/**
 * Helper function for registering our form field settings
 *
 * src: http://alisothegeek.com/2011/01/wordpress-settings-api-tutorial-1/
 * @param (array) $args The array of arguments to be used in creating the field
 * @return function call
 */
function wptuts_create_settings_field( $args = array() ) {
    // default array to overwrite when calling the function
    $defaults = array(
        ‘id’ => ‘default_field’, // the ID of the setting in our options array, and the ID of the HTML form element
        ‘title’ => ‘Default Field’, // the label for the HTML form element
        ‘desc’ => ‘This is a default description.’, // the description displayed under the HTML form element
        ‘std’ => », // the default value for this setting
        ‘type’ => ‘text’, // the HTML form element to use
        ‘section’ => ‘main_section’, // the section this setting belongs to — must match the array key of a section in wptuts_options_page_sections()
        ‘choices’ => array(), // (optional): the values in radio buttons or a drop-down menu
        ‘class’ => » // the HTML form element class.
    );
     
    // «extract» to be able to use the array keys as variables in our function output below
    extract( wp_parse_args( $args, $defaults ) );
     
    // additional arguments for use in form field output in the function wptuts_form_field_fn!
    $field_args = array(
        ‘type’ => $type,
        ‘id’ => $id,
        ‘desc’ => $desc,
        ‘std’ => $std,
        ‘choices’ => $choices,
        ‘label_for’ => $id,
        ‘class’ => $class
    );
 
    add_settings_field( $id, $title, ‘wptuts_form_field_fn’, __FILE__, $section, $field_args );
 
}

Поймите параметры add_settings_field()

Обратите внимание на параметры функции add_settings_field() . Информация взята со страницы Кодекса :

  • $id — Строка для использования в атрибуте ‘id’ тегов.
  • $title — Название поля.
  • $callback — имя функции обратного вызова, которая будет отображать поле формы.
  • $page$page настроек для отображения поля
  • $section — Раздел страницы настроек, в котором отображается поле
  • $args — Дополнительные аргументы для передачи нашей функции обратного вызова. (Это то, с чем мы в основном работаем, когда определяем нашу wptuts_options_page_fields() далее)

Приведенный ниже код должен быть записан в файле my-theme-options.php сразу после функции wptuts_options_page_sections() .

001
002
003
004
005
006
007
008
009
010
011
012
013
014
+015
016
+017
018
019
020
021
022
023
024
025
026
027
028
029
+030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
+055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/**
 * Define our form fields (settings)
 *
 * @return array
 */
function wptuts_options_page_fields() {
    // Text Form Fields section
    $options[] = array(
        «section» => «txt_section»,
        «id» => WPTUTS_SHORTNAME .
        «title» => __( ‘Text Input — Some HTML OK!’, ‘wptuts_textdomain’ ),
        «desc» => __( ‘A regular text input field. Some inline HTML (<a>, <b>, <em>, <i>, <strong>) is allowed.’, ‘wptuts_textdomain’ ),
        «type» => «text»,
        «std» => __(‘Some default value’,’wptuts_textdomain’)
    );
     
    $options[] = array(
        «section» => «txt_section»,
        «id» => WPTUTS_SHORTNAME .
        «title» => __( ‘No HTML!’, ‘wptuts_textdomain’ ),
        «desc» => __( ‘A text input field where no html input is allowed.’, ‘wptuts_textdomain’ ),
        «type» => «text»,
        «std» => __(‘Some default value’,’wptuts_textdomain’),
        «class» => «nohtml»
    );
     
    $options[] = array(
        «section» => «txt_section»,
        «id» => WPTUTS_SHORTNAME .
        «title» => __( ‘Numeric Input’, ‘wptuts_textdomain’ ),
        «desc» => __( ‘A text input field where only numeric input is allowed.’, ‘wptuts_textdomain’ ),
        «type» => «text»,
        «std» => «123»,
        «class» => «numeric»
    );
     
    $options[] = array(
        «section» => «txt_section»,
        «id» => WPTUTS_SHORTNAME .
        «title» => __( ‘Multinumeric Input’, ‘wptuts_textdomain’ ),
        «desc» => __( ‘A text input field where only multible numeric input (ie comma separated numeric values) is allowed.’, ‘wptuts_textdomain’ ),
        «type» => «text»,
        «std» => «123,234,345»,
        «class» => «multinumeric»
    );
     
    $options[] = array(
        «section» => «txt_section»,
        «id» => WPTUTS_SHORTNAME .
        «title» => __( ‘URL Input’, ‘wptuts_textdomain’ ),
        «desc» => __( ‘A text input field which can be used for urls.’, ‘wptuts_textdomain’ ),
        «type» => «text»,
        «std» => «http://wp.tutsplus.com»,
        «class» => «url»
    );
     
    $options[] = array(
        «section» => «txt_section»,
        «id» => WPTUTS_SHORTNAME .
        «title» => __( ‘Email Input’, ‘wptuts_textdomain’ ),
        «desc» => __( ‘A text input field which can be used for email input.’, ‘wptuts_textdomain’ ),
        «type» => «text»,
        «std» => «[email protected]»,
        «class» => «email»
    );
     
    $options[] = array(
        «section» => «txt_section»,
        «id» => WPTUTS_SHORTNAME .
        «title» => __( ‘Multi-Text Inputs’, ‘wptuts_textdomain’ ),
        «desc» => __( ‘A group of text input fields’, ‘wptuts_textdomain’ ),
        «type» => «multi-text»,
        «choices» => array( __(‘Text input 1′,’wptuts_textdomain’) . «|txt_input1», __(‘Text input 2′,’wptuts_textdomain’) . «|txt_input2», __(‘Text input 3′,’wptuts_textdomain’) . «|txt_input3», __(‘Text input 4′,’wptuts_textdomain’) . «|txt_input4»),
        «std» => «»
    );
     
    // Textarea Form Fields section
    $options[] = array(
        «section» => «txtarea_section»,
        «id» => WPTUTS_SHORTNAME .
        «title» => __( ‘Textarea — HTML OK!’, ‘wptuts_textdomain’ ),
        «desc» => __( ‘A textarea for a block of text. HTML tags allowed!’, ‘wptuts_textdomain’ ),
        «type» => «textarea»,
        «std» => __(‘Some default value’,’wptuts_textdomain’)
    );
 
    $options[] = array(
        «section» => «txtarea_section»,
        «id» => WPTUTS_SHORTNAME .
        «title» => __( ‘No HTML!’, ‘wptuts_textdomain’ ),
        «desc» => __( ‘A textarea for a block of text. No HTML!’, ‘wptuts_textdomain’ ),
        «type» => «textarea»,
        «std» => __(‘Some default value’,’wptuts_textdomain’),
        «class» => «nohtml»
    );
     
    $options[] = array(
        «section» => «txtarea_section»,
        «id» => WPTUTS_SHORTNAME .
        «title» => __( ‘No HTML! Line breaks OK!’, ‘wptuts_textdomain’ ),
        «desc» => __( ‘No HTML! Line breaks allowed!’, ‘wptuts_textdomain’ ),
        «type» => «textarea»,
        «std» => __(‘Some default value’,’wptuts_textdomain’),
        «class» => «allowlinebreaks»
    );
 
    $options[] = array(
        «section» => «txtarea_section»,
        «id» => WPTUTS_SHORTNAME .
        «title» => __( ‘Some Inline HTML ONLY!’, ‘wptuts_textdomain’ ),
        «desc» => __( ‘A textarea for a block of text.
            Only some inline HTML
            (<a>, <b>, <em>, <strong>, <abbr>, <acronym>, <blockquote>, <cite>, <code>, <del>, <q>, <strike>)
            is allowed!’, ‘wptuts_textdomain’ ),
        «type» => «textarea»,
        «std» => __(‘Some default value’,’wptuts_textdomain’),
        «class» => «inlinehtml»
    );
     
    // Select Form Fields section
    $options[] = array(
        «section» => «select_section»,
        «id» => WPTUTS_SHORTNAME .
        «title» => __( ‘Select (type one)’, ‘wptuts_textdomain’ ),
        «desc» => __( ‘A regular select form field’, ‘wptuts_textdomain’ ),
        «type» => «select»,
        «std» => «3»,
        «choices» => array( «1», «2», «3»)
    );
     
    $options[] = array(
        «section» => «select_section»,
        «id» => WPTUTS_SHORTNAME .
        «title» => __( ‘Select (type two)’, ‘wptuts_textdomain’ ),
        «desc» => __( ‘A select field with a label for the option and a corresponding value.’, ‘wptuts_textdomain’ ),
        «type» => «select2»,
        «std» => «»,
        «choices» => array( __(‘Option 1′,’wptuts_textdomain’) . «|opt1», __(‘Option 2′,’wptuts_textdomain’) . «|opt2», __(‘Option 3′,’wptuts_textdomain’) . «|opt3», __(‘Option 4′,’wptuts_textdomain’) . «|opt4»)
    );
     
    // Checkbox Form Fields section
    $options[] = array(
        «section» => «checkbox_section»,
        «id» => WPTUTS_SHORTNAME .
        «title» => __( ‘Checkbox’, ‘wptuts_textdomain’ ),
        «desc» => __( ‘Some Description’, ‘wptuts_textdomain’ ),
        «type» => «checkbox»,
        «std» => 1 // 0 for off
    );
     
    $options[] = array(
        «section» => «checkbox_section»,
        «id» => WPTUTS_SHORTNAME .
        «title» => __( ‘Multi-Checkbox’, ‘wptuts_textdomain’ ),
        «desc» => __( ‘Some Description’, ‘wptuts_textdomain’ ),
        «type» => «multi-checkbox»,
        «std» => »,
        «choices» => array( __(‘Checkbox 1′,’wptuts_textdomain’) . «|chckbx1», __(‘Checkbox 2′,’wptuts_textdomain’) . «|chckbx2», __(‘Checkbox 3′,’wptuts_textdomain’) . «|chckbx3», __(‘Checkbox 4′,’wptuts_textdomain’) . «|chckbx4»)
    );
     
    return $options;
}

Обратите внимание, как аргументы используются для каждого типа параметра, будь то поле ввода текста, текстовое поле, раскрывающийся список выбора или параметр флажка. Обратите внимание на аргумент section и его соответствие ключу массива $sections мы wptuts_options_page_sections() в нашей функции wptuts_options_page_sections() . Обратите внимание, что аргумент class регулярно используется для наших типов настроек text и textarea (это будет позже использовано в функции wptuts_validate_options() .)

Затем мы настраиваем вспомогательную функцию wptuts_get_settings() чтобы включить значение для переменной $output['wptuts_page_fields'] .

Код, приведенный ниже, и оставшаяся часть шага 4 должны быть записаны в файле my-theme-settings.php .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
/**
 * Helper function for defining variables for the current page
 *
 * @return array
 */
function wptuts_get_settings() {
     
    $output = array();
     
    // put together the output array
    $output[‘wptuts_option_name’] = ‘wptuts_options’;
    $output[‘wptuts_page_title’] = __( ‘Wptuts Settings Page’,’wptuts_textdomain’);
    $output[‘wptuts_page_sections’] = wptuts_options_page_sections();
    $output[‘wptuts_page_fields’] = wptuts_options_page_fields();
    $output[‘wptuts_contextual_help’] = »;
     
return $output;
}

Давайте зарегистрируем наши поля настроек, вызвав вспомогательную функцию wptuts_create_settings_field() которая в конечном итоге вызывает add_settings_field() . Помните, что так же, как разделы настроек, поля настроек, которые мы определили, хранятся в виде массива, поэтому нам нужно запустить цикл foreach .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/*
 * Register our setting
 */
function wptuts_register_settings(){
     
    // get the settings sections array
    $settings_output = wptuts_get_settings();
    $wptuts_option_name = $settings_output[‘wptuts_option_name’];
     
    //setting
    // register_setting( $option_group, $option_name, $sanitize_callback );
    register_setting($wptuts_option_name, $wptuts_option_name, ‘wptuts_validate_options’ );
     
    //sections
    // add_settings_section( $id, $title, $callback, $page );
    if(!empty($settings_output[‘wptuts_page_sections’])){
        // call the «add_settings_section» for each!
        foreach ( $settings_output[‘wptuts_page_sections’] as $id => $title ) {
            add_settings_section( $id, $title, ‘wptuts_section_fn’, __FILE__);
        }
    }
     
    //fields
    if(!empty($settings_output[‘wptuts_page_fields’])){
        // call the «add_settings_field» for each!
        foreach ($settings_output[‘wptuts_page_fields’] as $option) {
            wptuts_create_settings_field($option);
        }
    }
}

Наконец, мы определяем wptuts_form_field_fn() обратного вызова wptuts_form_field_fn() которая будет обрабатывать отображение поля формы. Скопируйте и вставьте следующий код сразу после функции wptuts_section_fn() .

001
002
003
004
005
006
007
008
009
010
011
012
013
014
+015
016
+017
018
019
020
021
022
023
024
025
026
027
028
029
+030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
+055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
/*
 * Form Fields HTML
 * All form field types share the same function!!
 * @return echoes output
 */
function wptuts_form_field_fn($args = array()) {
     
    extract( $args );
     
    // get the settings sections array
    $settings_output = wptuts_get_settings();
     
    $wptuts_option_name = $settings_output[‘wptuts_option_name’];
    $options = get_option($wptuts_option_name);
     
    // pass the standard value if the option is not yet set in the database
    if ( !isset( $options[$id] ) && ‘type’ != ‘checkbox’ ) {
        $options[$id] = $std;
    }
     
    // additional field class.
    $field_class = ($class != ») ?
     
     
    // switch html display based on the setting type.
    switch ( $type ) {
        case ‘text’:
            $options[$id] = stripslashes($options[$id]);
            $options[$id] = esc_attr( $options[$id]);
            echo «<input class=’regular-text$field_class’ type=’text’ id=’$id’ name='» .
            echo ($desc != ») ?
        break;
         
        case «multi-text»:
            foreach($choices as $item) {
                $item = explode(«|»,$item);
                $item[0] = esc_html__($item[0], ‘wptuts_textdomain’);
                if (!empty($options[$id])) {
                    foreach ($options[$id] as $option_key => $option_val){
                        if ($item[1] == $option_key) {
                            $value = $option_val;
                        }
                    }
                } else {
                    $value = »;
                }
                echo «<span>$item[0]:
            }
            echo ($desc != ») ?
        break;
         
        case ‘textarea’:
            $options[$id] = stripslashes($options[$id]);
            $options[$id] = esc_html( $options[$id]);
            echo «<textarea class=’textarea$field_class’ type=’text’ id=’$id’ name='» .
            echo ($desc != ») ?
        break;
         
        case ‘select’:
            echo «<select id=’$id’ class=’select$field_class’ name='» .
                foreach($choices as $item) {
                    $value = esc_attr($item, ‘wptuts_textdomain’);
                    $item = esc_html($item, ‘wptuts_textdomain’);
                     
                    $selected = ($options[$id]==$value) ?
                    echo «<option value=’$value’ $selected>$item</option>»;
                }
            echo «</select>»;
            echo ($desc != ») ?
        break;
         
        case ‘select2’:
            echo «<select id=’$id’ class=’select$field_class’ name='» .
            foreach($choices as $item) {
                 
                $item = explode(«|»,$item);
                $item[0] = esc_html($item[0], ‘wptuts_textdomain’);
                 
                $selected = ($options[$id]==$item[1]) ?
                echo «<option value=’$item[1]’ $selected>$item[0]</option>»;
            }
            echo «</select>»;
            echo ($desc != ») ?
        break;
         
        case ‘checkbox’:
            echo «<input class=’checkbox$field_class’ type=’checkbox’ id=’$id’ name='» .
            echo ($desc != ») ?
        break;
         
        case «multi-checkbox»:
            foreach($choices as $item) {
                 
                $item = explode(«|»,$item);
                $item[0] = esc_html($item[0], ‘wptuts_textdomain’);
                 
                $checked = »;
                 
                if ( isset($options[$id][$item[1]]) ) {
                    if ( $options[$id][$item[1]] == ‘true’) {
                        $checked = ‘checked=»checked»‘;
                    }
                }
                 
                echo «<input class=’checkbox$field_class’ type=’checkbox’ id=’$id|$item[1]’ name='» .
            }
            echo ($desc != ») ?
        break;
    }
}

Разбивка кода

Мы собираем наши поля настроек в переменной $options .

1
2
3
4
5
// get the settings sections array
$settings_output = wptuts_get_settings();
 
$wptuts_option_name = $settings_output[‘wptuts_option_name’];
$options = get_option($wptuts_option_name);

Мы передаем стандартное значение ( $std ), если настройка еще не установлена. Мы также собрали $field_class который будет использоваться в качестве класса поля ввода формы (при необходимости может использоваться для стилизации).

1
2
3
4
5
6
7
// pass the standard value if the option is not yet set in the database
if ( !isset( $options[$id] ) && ‘type’ != ‘checkbox’ ) {
    $options[$id] = $std;
}
 
// additional field class.
$field_class = ($class != ») ?

Затем мы запускаем цикл foreach и switch зависимости от типа поля настройки (текст, текстовое поле, выделение, флажок и т. Д.). Когда вы позже настроите эту функцию, вы захотите создать новый case для каждого нового типа поля настройки (примечание : type ) добавляешь.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// run a foreach and switch on option type
foreach ($options as $option) {
    switch ( $option[‘type’] ) {
        case ‘text’:
            // echo code
        break;
         
        case «multi-text»:
            // echo code
        break;
         
        case ‘textarea’:
            // echo code
        break;
         
        case ‘select’:
            // echo code
        break;
         
        case ‘select2’:
            // echo code
        break;
         
        case ‘checkbox’:
            // echo code
        break;
         
        case ‘multi-checkbox’:
            // echo code
        break;
    }
}

Если вы успешно выполнили все вышеперечисленное, вот так должна выглядеть ваша страница настроек на этом этапе. Обратите внимание, что ничего еще не спасет, поэтому не удивляйтесь, если ничего не случится, когда вы попытаетесь!


«Окончательный код, описанный в этом шаге, находится в папке Part One/source_ files/step5 »

Шаг 5 посвящен проверке и дезинфекции того, что пользователи пытаются сохранить, когда нажимают кнопку «Сохранить настройки». Этот процесс, также называемый «белым списком», является, на мой взгляд, наиболее важной частью этого урока. Если есть что-то, что мои пользователи темы произвели на меня неизгладимое впечатление, это проверить, подтвердить, подтвердить! Итак, в этом уроке мы создадим готовую к работе функцию обратного вызова проверки, которую вы можете использовать в своих проектах. Не стесняйтесь изменять, улучшать и расширять его в соответствии со своими потребностями.

Ой!и еще одна вещь, прежде чем мы перейдем к фактической функции проверки. Если вы заметили, что ваши настройки не сохраняются, даже когда все остальное выглядит хорошо, это место для устранения неполадок!
Итак, мы также рассмотрим совет по устранению неполадок, который может помочь.

Мы уже определили эту функцию в шаге 2, поэтому найдите ее в своем my-theme-settings.php. Затем скопируйте и вставьте завершенную функцию, которую вы видите ниже, на место.

001
002
003
004
005
006
007
008
009
010
011
012
013
014
+015
016
+017
018
019
020
021
022
023
024
025
026
027
028
029
+030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
+055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
/*
 * Validate input
 *
 * @return array
 */
function wptuts_validate_options($input) {
     
    // for enhanced security, create a new empty array
    $valid_input = array();
     
    // collect only the values we expect and fill the new $valid_input array ie whitelist our option IDs
     
        // get the settings sections array
        $settings_output = wptuts_get_settings();
         
        $options = $settings_output['wptuts_page_fields'];
         
        // run a foreach and switch on option type
        foreach ($options as $option) {
         
            switch ( $option['type'] ) {
                case ‘text’:
                    //switch validation based on the class!
                    switch ( $option['class'] ) {
                        //for numeric
                        case 'numeric':
                            //accept the input only when numeric!
                            $input[$option['id']] = trim($input[$option['id']]); // trim whitespace
                            $valid_input[$option['id']] = (is_numeric($input[$option['id']])) ? $input[$option['id']] : 'Expecting a Numeric value!';
                             
                            // register error
                            if(is_numeric($input[$option['id']]) == FALSE) {
                                add_settings_error(
                                    $option['id'], // setting title
                                    WPTUTS_SHORTNAME . '_txt_numeric_error', // error ID
                                    __('Expecting a Numeric value! Please fix.','wptuts_textdomain'), // error message
                                    'error' // type of message
                                );
                            }
                        break;
                         
                        //for multi-numeric values (separated by a comma)
                        case 'multinumeric':
                            //accept the input only when the numeric values are comma separated
                            $input[$option['id']] = trim($input[$option['id']]); // trim whitespace
                             
                            if($input[$option['id']] !=''){
                                1 |
                                $valid_input[$option['id']] = (preg_match('/^-?\d+(?:,\s?-?\d+)*$/', $input[$option['id']]) == 1) ? $input[$option['id']] : __('Expecting comma separated numeric values','wptuts_textdomain');
                            }else{
                                $valid_input[$option['id']] = $input[$option['id']];
                            }
                             
                            // register error
                            if($input[$option['id']] !='' && preg_match('/^-?\d+(?:,\s?-?\d+)*$/', $input[$option['id']]) != 1) {
                                add_settings_error(
                                    $option['id'], // setting title
                                    WPTUTS_SHORTNAME . '_txt_multinumeric_error', // error ID
                                    __('Expecting comma separated numeric values! Please fix.','wptuts_textdomain'), // error message
                                    'error' // type of message
                                );
                            }
                        break;
                         
                        //for no html
                        case 'nohtml':
                            //accept the input only after stripping out all html, extra white space etc!
                            $input[$option['id']] = sanitize_text_field($input[$option['id']]); // need to add slashes still before sending to the database
                            $valid_input[$option['id']] = addslashes($input[$option['id']]);
                        break;
                         
                        //for url
                        case 'url':
                            //accept the input only when the url has been sanited for database usage with esc_url_raw()
                            $input[$option['id']] = trim($input[$option['id']]); // trim whitespace
                            $valid_input[$option['id']] = esc_url_raw($input[$option['id']]);
                        break;
                         
                        //for email
                        case 'email':
                            //accept the input only after the email has been validated
                            $input[$option['id']] = trim($input[$option['id']]); // trim whitespace
                            if($input[$option['id']] != ''){
                                $valid_input[$option['id']] = (is_email($input[$option['id']])!== FALSE) ? $input[$option['id']] : __('Invalid email! Please re-enter!','wptuts_textdomain');
                            }elseif($input[$option['id']] == ''){
                                $valid_input[$option['id']] = __('This setting field cannot be empty! Please enter a valid email address.','wptuts_textdomain');
                            }
                             
                            // register error
                            if(is_email($input[$option['id']])== FALSE || $input[$option['id']] == '') {
                                add_settings_error(
                                    $option['id'], // setting title
                                    WPTUTS_SHORTNAME . '_txt_email_error', // error ID
                                    __('Please enter a valid email address.','wptuts_textdomain'), // error message
                                    'error' // type of message
                                );
                            }
                        break;
                         
                        // a "cover-all" fall-back when the class argument is not set
                        default:
                            // accept only a few inline html elements
                            $allowed_html = array(
                                'a' => array('href' => array (),'title' => array ()),
                                'b' => array(),
                                'em' => array (),
                                'i' => array (),
                                ‘strong’ => array()
                            );
                             
                            $input[$option['id']] = trim($input[$option['id']]); // trim whitespace
                            $input[$option['id']] = force_balance_tags($input[$option['id']]); // find incorrectly nested or missing closing tags and fix markup
                            $input[$option['id']] = wp_kses( $input[$option['id']], $allowed_html); // need to add slashes still before sending to the database
                            $valid_input[$option['id']] = addslashes($input[$option['id']]);
                        break;
                    }
                break;
                 
                case "multi-text":
                    // this will hold the text values as an array of 'key' => 'value'
                    unset($textarray);
                     
                    $text_values = array();
                    foreach ($option['choices'] as $k => $v ) {
                        // explode the connective
                        $pieces = explode("|", $v);
                         
                        $text_values[] = $pieces[1];
                    }
                     
                    foreach ($text_values as $v ) {    
                         
                        // Check that the option isn't empty
                        if (!empty($input[$option['id'] . '|' . $v])) {
                            // If it's not null, make sure it's sanitized, add it to an array
                            switch ($option['class']) {
                                // different sanitation actions based on the class create you own cases as you need them
                                 
                                //for numeric input
                                case 'numeric':
                                    //accept the input only if is numberic!
                                    .
                                    .
                                break;
                                 
                                // a "cover-all" fall-back when the class argument is not set
                                default:
                                    // strip all html tags and white-space.
                                    .
                                    .
                                break;
                            }
                            // pass the sanitized user input to our $textarray array
                            .
                         
                        } else {
                            $textarray[$v] = '';
                        }
                    }
                    // pass the non-empty $textarray to our $valid_input array
                    if (!empty($textarray)) {
                        $valid_input[$option['id']] = $textarray;
                    }
                break;
                 
                case ‘textarea’:
                    //switch validation based on the class!
                    switch ( $option['class'] ) {
                        //for only inline html
                        case 'inlinehtml':
                            // accept only inline html
                            $input[$option['id']] = trim($input[$option['id']]); // trim whitespace
                            $input[$option['id']] = force_balance_tags($input[$option['id']]); // find incorrectly nested or missing closing tags and fix markup
                            $input[$option['id']] = addslashes($input[$option['id']]); //wp_filter_kses expects content to be escaped!
                            $valid_input[$option['id']] = wp_filter_kses($input[$option['id']]); //calls stripslashes then addslashes
                        break;
                         
                        //for no html
                        case 'nohtml':
                            //accept the input only after stripping out all html, extra white space etc!
                            $input[$option['id']] = sanitize_text_field($input[$option['id']]); // need to add slashes still before sending to the database
                            $valid_input[$option['id']] = addslashes($input[$option['id']]);
                        break;
                         
                        //for allowlinebreaks
                        case 'allowlinebreaks':
                            //accept the input only after stripping out all html, extra white space etc!
                            $input[$option['id']] = wp_strip_all_tags($input[$option['id']]); // need to add slashes still before sending to the database
                            $valid_input[$option['id']] = addslashes($input[$option['id']]);
                        break;
                         
                        // a "cover-all" fall-back when the class argument is not set
                        default:
                            // accept only limited html
                            //my allowed html
                            $allowed_html = array(
                                'a' => array('href' => array (),'title' => array ()),
                                'b' => array(),
                                'blockquote' => array('cite' => array ()),
                                'br' => array(),
                                'dd' => array(),
                                'dl' => array(),
                                'dt' => array(),
                                'em' => array (),
                                'i' => array (),
                                'li' => array(),
                                'ol' => array(),
                                'p' => array(),
                                'q' => array('cite' => array ()),
                                ‘strong’ => array(),
                                'ul' => array(),
                                'h1' => array('align' => array (),'class' => array (),'id' => array (), 'style' => array ()),
                                'h2' => array('align' => array (),'class' => array (),'id' => array (), 'style' => array ()),
                                'h3' => array('align' => array (),'class' => array (),'id' => array (), 'style' => array ()),
                                'h4' => array('align' => array (),'class' => array (),'id' => array (), 'style' => array ()),
                                'h5' => array('align' => array (),'class' => array (),'id' => array (), 'style' => array ()),
                                'h6' => array('align' => array (),'class' => array (),'id' => array (), 'style' => array ())
                            );
                             
                            $input[$option['id']] = trim($input[$option['id']]); // trim whitespace
                            $input[$option['id']] = force_balance_tags($input[$option['id']]); // find incorrectly nested or missing closing tags and fix markup
                            $input[$option['id']] = wp_kses( $input[$option['id']], $allowed_html); // need to add slashes still before sending to the database
                            $valid_input[$option['id']] = addslashes($input[$option['id']]);                           
                        break;
                    }
                break;
                 
                case ‘select’:
                    // check to see if the selected value is in our approved array of values!
                    $valid_input[$option['id']] = (in_array( $input[$option['id']], $option['choices']) ? $input[$option['id']] : '' );
                break;
                 
                case 'select2':
                    // process $select_values
                        $select_values = array();
                        foreach ($option['choices'] as $k => $v) {
                            // explode the connective
                            $pieces = explode("|", $v);
                             
                            $select_values[] = $pieces[1];
                        }
                    // check to see if selected value is in our approved array of values!
                    $valid_input[$option['id']] = (in_array( $input[$option['id']], $select_values) ? $input[$option['id']] : '' );
                break;
                 
                case ‘checkbox’:
                    // if it's not set, default to null!
                    if (!isset($input[$option['id']])) {
                        $input[$option['id']] = null;
                    }
                    // Our checkbox value is either 0 or 1
                    $valid_input[$option['id']] = ( $input[$option['id']] == 1 ? 1 : 0 );
                break;
                 
                case 'multi-checkbox':
                    unset($checkboxarray);
                    $check_values = array();
                    foreach ($option['choices'] as $k => $v ) {
                        // explode the connective
                        $pieces = explode("|", $v);
                         
                        $check_values[] = $pieces[1];
                    }
                     
                    foreach ($check_values as $v ) {       
                         
                        // Check that the option isn't null
                        if (!empty($input[$option['id'] . '|' . $v])) {
                            // If it's not null, make sure it's true, add it to an array
                            $checkboxarray[$v] = 'true';
                        }
                        else {
                            $checkboxarray[$v] = 'false';
                        }
                    }
                    // Take all the items that were checked, and set them as the main option
                    if (!empty($checkboxarray)) {
                        $valid_input[$option['id']] = $checkboxarray;
                    }
                break;
                 
            }
        }
return $valid_input; // return validated input
}

Разбивка кода

Некоторые из этих процессов могут напоминать вам о том, что мы сделали в функции обратного вызова полей настройки, которая обрабатывала отображение поля формы на странице.

Мы собираем наши поля настроек в $optionsпеременной.

1
2
3
4
// get the settings sections array
    $settings_output = wptuts_get_settings();
     
    $options = $settings_output['wptuts_page_fields'];

Затем мы запускаем foreachцикл и switchна основе типа поля настройки (текст, текстовое поле, выбор, флажок и т. Д.). Когда вы позже настроите эту функцию, вы захотите создать новую caseдля каждого нового типа поля настройки (примечание: тип ) вы добавляете.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// run a foreach and switch on option type
    foreach ($options as $option) {
        switch ( $option['type'] ) {
            case ‘text’:
                // validation code
            break;
             
            case "multi-text":
                // validation code
            break;
             
            case ‘textarea’:
                // validation code
            break;
             
            case ‘select’:
                // validation code
            break;
             
            case 'select2':
                // validation code
            break;
             
            case ‘checkbox’:
                // validation code
            break;
             
            case 'multi-checkbox':
                // validation code
            break;
        }
    }

Каждый тип поля настройки, в частности, текст и типы текстовой области, могут использоваться для различного пользовательского ввода. Иногда входными данными может быть какой-то текст, в котором разрешены html-элементы, но в других случаях может оказаться, что html не разрешен, или только встроенный html — это нормально. Некоторые настройки могут ожидать ввода числового значения, адреса электронной почты или URL Все это должно быть правильно проверено, и вот где classаргумент в нашей wptuts_options_page_fields()функции входит.

Мы запускаем секунду, switchосновываясь на классе поля настроек (nohtml, numeric, email, url и т. Д.), Который будет содержать различный код проверки / очистки в зависимости от того, что необходимо. Когда вы позже настроите эту функцию, вы захотите создать новый caseдля каждого нового класса поля настроек, который вы можете создать. Написано ниже, вы видите класс switchдля типа поля настройки текста. Найдите минутку, чтобы изучить класс, switchиспользуемый для поля настроек textarea.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
switch ( $option['type'] ) {
    case ‘text’:
        //switch validation based on the class!
        switch ( $option['class'] ) {
             
            //for numeric
            case 'numeric':
                // validation code
            break;
             
            //for multi numeric separated with a comma
            case 'multinumeric':
                // validation code
            break;
             
            //for no html
            case 'nohtml':
                // validation code
            break;
             
            //for url
            case 'url':
                // validation code
            break;
             
            //for email
            case 'email':
                // validation code
            break;
         
            // a "cover-all" fall-back when the class argument is not set
            default:
                // validation code
            break;
        }
    break;

Потратьте время на изучение проверки / санитарии, проведенной в каждом case. Если вы видите какие-либо используемые функции, в которых вы не уверены, посмотрите их. Хороший ресурс для проверки данных находится в Кодексе

Устранение неполадок с настройками, которые не сохраняются

Если вы заметили, что ваши настройки не сохраняются, первое, что нужно сделать, — это print_rкак входящие $inputв верхней части функции проверки, так и исходящие $valid_inputв конце, прежде чем она будет возвращена.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
function wptuts_validate_options($input) {
    ?><pre><?php
        print_r($input);
    ?></pre><?php
 
    /*
    validation code
    */
     
    ?><pre><?php
        print_r($valid_input);
    ?></pre><?php
    exit;
return $valid_input;
}

Если код проверки, который вы используете, написан плохо, то $valid_inputзначения массива будут пустыми, даже если $inputзначения массива выглядят нормально. Изолируйте проблемные настройки и проверьте код проверки, чтобы выяснить, что может препятствовать $inputпередаче значения определенного ключа в качестве значения соответствующего $valid_inputключа.

Проходя код проверки, вы заметите, что в основном мы берем пользовательский ввод, «очищаем его» и затем передаем в наш проверенный массив ввода. Однако в некоторых случаях, например, при вводе электронной почты, мы будем требовать, чтобы пользователь исправил свои данные перед сохранением значения в базе данных. Мы должны сообщить пользователю, что есть проблема, то есть его ввод неверен и что ему нужно повторно ввести нужное значение правильно. API настроек WordPress позволяет нам предоставлять такие отзывы, используя add_settings_error()функцию.

Вы увидите, что эта функция используется в нашем поле типа текстового поля и, в частности, для числовых, многозначных классов и классов электронной почты. Ниже показана проверка, выполненная в поле ввода электронной почты.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
//for email
case 'email':
    //accept the input only after email has been validated
    $input[$option['id']] = trim($input[$option['id']]); // trim whitespace
    if($input[$option['id']] != ''){
        $valid_input[$option['id']] = (is_email($input[$option['id']])!== FALSE) ? $input[$option['id']] : __('Invalid email! Please re-enter!','wptuts_textdomain');
    }elseif($input[$option['id']] == ''){
        $valid_input[$option['id']] = __('This setting field cannot be empty! Please enter a valid email address.','wptuts_textdomain');
    }
     
    // register error
    if(is_email($input[$option['id']])== FALSE || $input[$option['id']] == '') {
        add_settings_error(
            $option['id'], // setting title
            WPTUTS_SHORTNAME . '_txt_email_error', // error ID
            __('Please enter a valid email address.','wptuts_textdomain'), // error message
            'error' // type of message
        );
    }
break;

Понять add_settings_error()параметры

Обратите внимание на add_settings_error()параметры функции. Информация взята со страницы Кодекса :

  • $setting — заголовок настройки, к которой относится эта ошибка.
  • $code— Slug-name для идентификации ошибки. Используется как часть атрибута id в выводе HTML.
  • $message — Форматированный текст сообщения для отображения пользователю (будет отображаться в стилях <div> и <p>)
  • $type — Тип сообщения (ошибка или обновление), управляет классом HTML.

Если вы успешно выполнили все вышесказанное, то теперь вы сможете редактировать и сохранять свои настройки! Вы не увидите никаких сообщений администратора (ни «успех», ни «ошибка») — мы все равно должны написать это (см. Шаг 6) — однако ваши настройки будут проверены и сохранены.


«Окончательный код, описанный в этом шаге, находится в Part One/source_ files/step6папке»

На шаге 5 мы говорили о внесении в белый список наших настроек и их сохранении. Это все хорошо, однако, мы должны предоставить некоторую обратную связь, когда настройки успешно сохраняются и когда возникают ошибки. Шаг 6 говорит об отображении такой обратной связи в виде сообщений администратора.

WordPress предоставляет нам ловушку действий, которую мы можем использовать для вывода сообщений администратора, и это то, что мы будем использовать для отображения отзывов как об «успехе», так и об «ошибке». Сначала мы создадим вспомогательную функцию с 2 параметрами: фактическое сообщение и тип сообщения («ошибка», «информация», «обновление» и т. Д.). Я видел это на Wp Recipes, и мне понравилось, как это было сделано, мы будем использовать и здесь.

Код, приведенный ниже и для оставшейся части шага 6, должен быть записан в my-theme-settings.phpфайле сразу после wptuts_validate_options()функции.

01
02
03
04
05
06
07
08
09
10
11
/**
 * Helper function for creating admin messages
 *
 * @param (string) $message The message to echo
 * @param (string) $msgclass The message class
 * @return echoes the message
 */
function wptuts_show_msg($message, $msgclass = 'info') {
    echo "<div id='message' class='$msgclass'>$message</div>";
}

Далее нам нужно написать нашу функцию обратного вызова, которая будет подключена к admin_notices

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
 * Callback function for displaying admin messages
 *
 * @return calls wptuts_show_msg()
 */
function wptuts_admin_msgs() {
     
    // check for our settings page - need this in conditional further down
    $wptuts_settings_pg = strpos($_GET['page'], WPTUTS_PAGE_BASENAME);
    // collect setting errors/notices: //http://codex.wordpress.org/Function_Reference/get_settings_errors
    $set_errors = get_settings_errors();
     
    //display admin message only for the admin to see, only on our settings page and only when setting errors/notices are returned!
    if(current_user_can ('manage_options') && $wptuts_settings_pg !== FALSE && !empty($set_errors)){
 
        // have our settings succesfully been updated?
        if($set_errors[0]['code'] == 'settings_updated' && isset($_GET['settings-updated'])){
            wptuts_show_msg("<p>" . $set_errors[0]['message'] . "</p>", 'updated');
         
        // have errors been found?
        }else{
            // there maybe more than one so run a foreach loop.
            foreach($set_errors as $set_error){
                // set the title attribute to match the error "setting title" - need this in js file
                wptuts_show_msg("<p class='setting-error-message' title='" . $set_error['setting'] . "'>" . $set_error['message'] . "</p>", 'error');
            }
        }
    }
}
 
// admin messages hook!
add_action('admin_notices', 'wptuts_admin_msgs');

Понять функцию

Я тщательно прокомментировал функцию, однако следует отметить, что get_settings_errors()функция будет возвращать не только сообщения об ошибках, но и все уведомления в целом, включая успешное сообщение, когда наши настройки сохраняются правильно. Так что не позволяйте имени функции вводить вас в заблуждение! Вот почему мы можем использовать ту же функцию для отображения сообщения администратора «Настройки сохранены» в «успехе», а также сообщений об ошибках «ошибка».

Если вы успешно выполнили вышесказанное, то теперь вы сможете увидеть успешные «Настройки сохранены». сообщение администратора, когда вы проходите проверку ввода, а также сообщение об ошибке администратора, если вы этого не сделаете.

Теперь, когда сообщение об ошибке отображается должным образом, давайте добавим немного javascript, чтобы привлечь внимание к настройке, которую пользователь должен исправить. На самом деле вы уже загрузили код на свой сервер. Вы сделали это уже на шаге 1, поэтому все, что нам нужно сделать, это просто включить необходимые файлы на нашей странице настроек, чтобы браузер мог выполнить скрипт. Скопируйте и вставьте следующую wptuts_add_menu()функцию выше .

1
2
3
4
5
6
7
/*
 * Group scripts (js & css)
 */
function wptuts_settings_scripts(){
    wp_enqueue_style('wptuts_theme_settings_css', get_template_directory_uri() . '/lib/css/wptuts_theme_settings.css');
    wp_enqueue_script( 'wptuts_theme_settings_js', get_template_directory_uri() . '/lib/js/wptuts_theme_settings.js', array('jquery'));
}

Затем мы настраиваем wptuts_add_menu()функцию следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
/*
 * The Admin menu page
 */
function wptuts_add_menu(){
     
    // Display Settings Page link under the "Appearance" Admin Menu
    // add_theme_page( $page_title, $menu_title, $capability, $menu_slug, $function);
    $wptuts_settings_page = add_theme_page(__('Wptuts Options'), __('Wptuts Options','wptuts_textdomain'), 'manage_options', WPTUTS_PAGE_BASENAME, 'wptuts_settings_page_fn');
         
    // css & js
    add_action( 'load-'. $wptuts_settings_page, 'wptuts_settings_scripts' );   
}

Что говорит код js?

Загляните внутрь twentyeleven/lib/jsпапки и откройте файл, который вы видите внутри: wptuts_theme_settings.jsв вашем редакторе кода.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
jQuery(function(){
    var error_msg = jQuery("#message p[class='setting-error-message']");
    // look for admin messages with the "setting-error-message" error class
    if (error_msg.length != 0) {
        // get the title
        var error_setting = error_msg.attr('title');
         
        // look for the label with the "for" attribute=setting title and give it an "error" class (style this in the css file!)
        jQuery("label[for='" + error_setting + "']").addClass('error');
         
        // look for the input with id=setting title and add a red border to it.
        jQuery("input[id='" + error_setting + "']").attr('style', 'border-color: red');
    }
});

Мы ищем любые сообщения администратора с классом setting-error-message. Если у нас есть какое-либо отображение на странице, мы продолжаем и получаем titleатрибут сообщения об ошибке . Это всегда будет соответствовать метке настройки ( forатрибуту) и полю формы ввода ( idатрибуту). Все, что осталось сделать, это добавить класс ошибки к метке и стиль границы в поле формы ввода. Обратите внимание, что класс ошибки затем стилизуется в файле css ( twentyeleven/lib/css/wptuts_theme_settings.css). Когда вы откроете файл CSS, вы увидите, что он практически пуст. Используйте его, чтобы добавить дополнительные стили к странице настроек.

Если вы успешно выполнили вышеприведенное, настройки ошибок должны быть выделены красным, когда сообщения об ошибках отображаются так, как показано ниже


«Окончательный код, описанный в этом шаге, находится в Part One/source_ files/step7/ my-theme-settings.phpпапке»

Последний шаг 7 в этом уроке будет касаться добавления контекстной справки на нашу страницу настроек. Эта дополнительная информация будет расположена внутри панели, которая открывается при нажатии на вкладку «Справка», расположенную в правом верхнем углу экрана администратора. Что нам нужно сделать, это написать текст, который мы хотим, а затем сообщить WordPress, где мы хотим, чтобы он отображался.

Откройте свой my-theme-options.phpфайл в редакторе кода. Скопируйте и вставьте функцию, которую вы видите ниже

01
02
03
04
05
06
07
08
09
10
11
/**
 * Contextual Help
 */
function wptuts_options_page_contextual_help() {
     
    $text = "<h3>" . __('Wptuts Settings - Contextual Help','wptuts_textdomain') . "</h3>";
    $text .= "<p>" . __('Contextual help goes here. You may want to use different html elements to format your text as you want.','wptuts_textdomain') . "</p>";
     
    // return text
    return $text;
}

Сначала нам нужно настроить нашу вспомогательную wptuts_get_settings()функцию, чтобы включить значение для $output['wptuts_contextual_help'].

Код, приведенный ниже, и оставшаяся часть шага 7 должны быть записаны в my-theme-settings.phpфайле.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
/**
 * Helper function for defining variables for the current page
 *
 * @return array
 */
function wptuts_get_settings() {
     
    $output = array();
     
    // put together the output array
    $output['wptuts_option_name'] = 'wptuts_options';
    $output['wptuts_page_title'] = __( 'Wptuts Settings Page','wptuts_textdomain');
    $output['wptuts_page_sections'] = wptuts_options_page_sections();
    $output['wptuts_page_fields'] = wptuts_options_page_fields();
    $output['wptuts_contextual_help'] = wptuts_options_page_contextual_help();
     
return $output;
}

Затем мы настраиваем нашу wptuts_add_menu()функцию в последний раз. Мы вызываем add_contextual_help()функцию, которая принимает два параметра:
$screen(наша страница настроек) и $text(текст справки, из которого мы выводим wptuts_options_page_contextual_help())

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
/*
 * The Admin menu page
 */
function wptuts_add_menu(){
     
    $settings_output = wptuts_get_settings();
    // collect our contextual help text
    $wptuts_contextual_help = $settings_output['wptuts_contextual_help'];
     
    // Display Settings Page link under the "Appearance" Admin Menu
    $wptuts_settings_page = add_theme_page(__('Wptuts Options'), __('Wptuts Options','wptuts_textdomain'), 'manage_options', WPTUTS_PAGE_BASENAME, 'wptuts_settings_page_fn');
        // contextual help
        if ($wptuts_settings_page) {
            add_contextual_help( $wptuts_settings_page, $wptuts_contextual_help );
        }
        // css & js
        add_action( 'load-'. $wptuts_settings_page, 'wptuts_settings_scripts' );
}

Если вы успешно выполнили вышеуказанное, то наш тест контекстной справки должен отображаться на вкладке «Справка», как показано ниже.


И последнее, но не менее важное: мы хотим посмотреть, как мы можем использовать настройки нашей темы в наших файлах шаблонов тем. Скопируйте и вставьте следующий код в twentyeleven/functions.phpпосле twentyeleven_setup()функции.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
 * Collects our theme options
 *
 * @return array
 */
function wptuts_get_global_options(){
     
    $wptuts_option = array();
 
    $wptuts_option = get_option('wptuts_options');
     
return $wptuts_option;
}
 
 /**
 * Call the function and collect in variable
 *
 * Should be used in template files like this:
 ?>
 *
 * Note: Should you notice that the variable ($wptuts_option) is empty when used in certain templates such as header.php, sidebar.php and footer.php
 * you will need to call the function (copy the line below and paste it) at the top of those documents (within php tags)!
 */
$wptuts_option = wptuts_get_global_options();

Наши настройки были сохранены в одном массиве с именем опции wptuts_options. Чтобы получить их мы звоним get_option('wptuts_options'). Как вы можете видеть, это делается внутри нашей функции wptuts_get_global_options(), выход которой собирается в $wptuts_optionпеременной.

Примечание: если вы чувствуете, что wptuts_get_global_options()функция несколько избыточна, не делайте этого. Его использование будет иметь больше смысла, как только вы пройдете вторую часть этой серии.

Отобразите конкретную опцию в любом из ваших шаблонов тем, например: <?php echo $wptuts_option['wptuts_txt_input']; ?>— значение в скобках — это идентификатор опции, которую вы хотите отобразить.

Вы заметите, что когда вы попытаетесь повторить вышеизложенное в шаблонах header.php, sidebar.phpи footer.phpничего не произойдет! Это не так в других шаблонах WordPress ( index.phpи page.phpт. Д.). Попробуйте сами, чтобы увидеть.

Скопируйте и вставьте следующее в тег twentyeleven/header.phpпосле <body>и посмотрите, как он возвращается NULLво внешнем интерфейсе.

1
<pre><?php var_dump($wptuts_option);?></pre>

Теперь скопируйте и вставьте следующее сразу после wp_head();звонка.

1
$wptuts_option = wptuts_get_global_options();

Обратите внимание, что переменная теперь возвращает все настройки нашей темы. Просто помните , что когда вы пытаетесь параметры отображения в настройках темы в header.php, sidebar.phpи footer.phpшаблоны темы.


Надеюсь, вам понравилась первая часть, и я с нетерпением жду ваших комментариев о том, что вы об этом думаете. Вторая часть (завтра!) Покажет, как мы можем создавать меню администратора верхнего уровня с несколькими страницами настроек. Мы также добавим некоторые вкладки, чтобы вы могли увидеть, как можно создать страницу настроек с вкладками.