WordPress как на ладони
wordpress jino

API настроек (опций)

API опций было добавлено в версии 2.7 и позволяет создавать поля форм (опции), которые будут обрабатываться автоматически (сохраняться в БД и выводиться на экран). Такой подход дает возможность удобно добавлять свои опции и блоки опций в уже существующие страницы настроек (Общие, Чтение, Медиафайлы и т.д.). Или можно создавать страницы настроек плагинов без использования лишнего кода.

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

Оглавление:

Заметка: все post данные формы должны отправляться на страницу wp-admin/options.php. Пользователи должны проходить проверку возможности: manage_options, а в мультисайтовых версиях должны быть Супер Админами (Super Admin), чтобы отправлять данные формы.

register_setting() и все функции регистрации опций и их блоков: add_settings_*(), должны вызываться в момент срабатывания хука admin_init

Функции API

Регистрация/удаление опций
Добавление блоков и отдельных полей
Вывод на экран
Ошибки

Добавление полей опций

Новое поле опции можно добавить в секцию на уже существующую страницу опций WordPress или на страницу опций плагина. Для этого используется функция add_settings_field().

Функция обратного вызова (callback) должна выводить html код поля input. Значение value поля также должно заполнятся. WordPress сам позаботится о сохранении опции в базу данных (обычно сохраняется в таблицу wp_options, но можно и перенастроить).

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

add_settings_field( $id, $title, $callback, $page, $section = 'default', $args = array() );
  • $id - Ярлык (slug) опции, используется как идентификатор поля. Используется в ID атрибуте тега.

  • $title - заголовок поля.

  • $callback - название функции обратного вызова. Функция должна заполнять поле нужным <input> тегом, который станет частью одной большой формы. Атрибут name должен быть равен параметру $option_name из register_setting(). Атрибут id обычно равен параметру $id. Результат должен сразу выводиться на экран (echo).

  • $page - страница меню в которую будет добавлено поле. Указывать нужно sug страницы, т.е. параметр должен быть равен параметру $menu_slug из add_theme_page(). У базовых страниц WordPress названия равны: general, reading, writing и т.д. по аналогии...

  • $section - название секции страницы настроек, в которую должно быть добавлено поле. По умолчанию default или может быть секцией добавленной функцией add_settings_section.

  • $args - дополнительные параметры, которые должны быть переданы callback функции.

Добавление секции опций

Секции опций - это блоки опций выделенные заголовком. Вместо того, чтобы создавать новую страницу настроек, иногда разумнее добавить новую секцию на уже существующую страницу настроек WordPress - это сделает плагин более простым и WordPress не будет нагружен новой страницей настроек плагина.

add_settings_section( $id, $title, $callback, $page );
  • $id - идентификатор секции. К этому ID прикрепляются поля (см. add_settings_field()).

  • $title - заголовок секции (название блока).

  • $callback - функция обратного вызова, которая выполняется в начале секции, перед выводом полей. В ней можно вывести текст описывающий секцию, выводить нужно сразу на экран, используя echo.

  • $page -  тип страницы настроек, на которой будет показана секция (general, reading, writing, ...).

Регистрация опций

register_setting( $option_group, $option_name, $sanitize_callback );
unregister_setting( $option_group, $option_name, $sanitize_callback );
  • $option_group - название группы, к которой относится опция. Должна совпадать с группой в функции  settings_fields().

  • $option_name - название опции, которая будет сохраняться.

  • $sanitize_callback - функция обратного вызова, которая будет обрабатывать значение перед сохранением.

Вывод секции опций на экран

Когда API используется для добавления опций к уже существующей странице опций, нет необходимости беспокоится о html теге самой формы, потому что она уже добавлена на странице и опции (input поля) будут вставляться внутри этой формы. Однако, когда вы создаете новую страницу опций, то вам нужно указать HTML тег формы (form) и его структуру.

settings_fields

Чтобы вывести скрытые поля и обеспечить безопасность данных формы опций, используйте функцию settings_fields(): settings_fields( $option_group );

  • $option_group - название группы. Должно совпадать с таким же параметром у  register_setting(). Это название страницы (её slug) на которой выводятся опции.
do_settings_sections

Чтобы вывести секцию предназначенную для страницы опций, нужно использовать функцию do_settings_sections()do_settings_sections( $page );

  • $page - альтернативное название (slug) страницы секции которой нужно вывести. Должен совпадать с названием страницы в функции add_settings_section().

Функция do_settings_fields() похожа на do_settings_sections(), она также выводит поля для определенной страницы и секции, только эти поля не форматируются в табличный вид, а выводятся как есть. Обычно не нужно вызывать эту функцию напрямую, а нужно использовать do_settings_sections(), чтобы вывести поля опций связанные с секцией.

submit_button

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

Вывод всего блока формы

И в заключении вам нужно будет добавить HTML тег <form> в котором указать атрибуты action="options.php" method="POST". Этот пример, показывает как правильно выводить форму для отдельной страницы опций, с использованием ранее зарегистрированных полей:

<form method="POST" action="options.php">
<?php 
settings_fields( 'my-page' );  // название группы опций - register_setting( $option_group )
do_settings_sections( 'my-page' ); // slug страницы на которой выводится форма
submit_button();
?>
</form>

Примеры

#1. Дополнительные опции на странице настройки WordPress "Чтение"

Добавим новую секцию с двумя новыми опциями на базовую страницу настроек WordPress "Чтение"

// ------------------------------------------------------------------
// Вешаем все блоки, поля и опции на хук admin_init
// ------------------------------------------------------------------
//
add_action( 'admin_init', 'eg_settings_api_init' );
function eg_settings_api_init() {
	// Добавляем блок опций на базовую страницу "Чтение"
	add_settings_section(
		'eg_setting_section', // секция
		'Заголовок для секции настроек',
		'eg_setting_section_callback_function',
		'reading' // страница
	);

	// Добавляем поля опций. Указываем название, описание, 
	// функцию выводящую html код поля опции.
	add_settings_field(
		'eg_setting_name',
		'Описание поля опции',
		'eg_setting_callback_function', // можно указать ''
		'reading', // страница
		'eg_setting_section' // секция
	);
	add_settings_field(
		'eg_setting_name2',
		'Описание поля опции2',
		'eg_setting_callback_function2',
		'reading', // страница
		'eg_setting_section' // секция
	);

	// Регистрируем опции, чтобы они сохранялись при отправке 
	// $_POST параметров и чтобы callback функции опций выводили их значение.
	register_setting( 'reading', 'eg_setting_name' );
	register_setting( 'reading', 'eg_setting_name2' );
}

// ------------------------------------------------------------------
// Сallback функция для секции
// ------------------------------------------------------------------
//
// Функция срабатывает в начале секции, если не нужно выводить 
// никакой текст или делать что-то еще до того как выводить опции, 
// то функцию можно не использовать для этого укажите '' в третьем 
// параметре add_settings_section
//
function eg_setting_section_callback_function() {
	echo '<p>Текст описывающий блок настроек</p>';
}

// ------------------------------------------------------------------
// Callback функции выводящие HTML код опций
// ------------------------------------------------------------------
//
// Создаем checkbox и text input теги
//
function eg_setting_callback_function() {
	echo '<input 
		name="eg_setting_name" 
		type="checkbox" 
		' . checked( 1, get_option( 'eg_setting_name' ), false ) . ' 
		value="1" 
		class="code" 
	/>';
}
function eg_setting_callback_function2() {
	echo '<input 
		name="eg_setting_name2"  
		type="text" 
		value="' . get_option( 'eg_setting_name2' ) . '" 
		class="code2"
	 />';
}

Что получилось и какой блок за что отвечает:

Графическое изображение кода - что за что отвечает.

#2. Страница настроек плагина (опции в массиве)

Давайте создадим плагин, в котором будет только страница настроек. Сделаем мы это, чтобы разобраться как работает API настроек.

Здесь регистрируется одна опция и в нее добавляются несколько разных опций как массив данных. Так удобнее и практичнее.

<?php
/*
 * Plugin name: Primer
 * Description: Демонстрация создания страницы настроек для плагина
*/

/**
 * Создаем страницу настроек плагина
 */
add_action('admin_menu', 'add_plugin_page');
function add_plugin_page(){
	add_options_page( 'Настройки Primer', 'Primer', 'manage_options', 'primer_slug', 'primer_options_page_output' );
}

function primer_options_page_output(){
	?>
	<div class="wrap">
		<h2><?php echo get_admin_page_title() ?></h2>

		<form action="options.php" method="POST">
			<?php
				settings_fields( 'option_group' );     // скрытые защитные поля
				do_settings_sections( 'primer_page' ); // секции с настройками (опциями). У нас она всего одна 'section_id'
				submit_button();
			?>
		</form>
	</div>
	<?php
}

/**
 * Регистрируем настройки.
 * Настройки будут храниться в массиве, а не одна настройка = одна опция.
 */
add_action('admin_init', 'plugin_settings');
function plugin_settings(){
	// параметры: $option_group, $option_name, $sanitize_callback
	register_setting( 'option_group', 'option_name', 'sanitize_callback' );

	// параметры: $id, $title, $callback, $page
	add_settings_section( 'section_id', 'Основные настройки', '', 'primer_page' ); 

	// параметры: $id, $title, $callback, $page, $section, $args
	add_settings_field('primer_field1', 'Название опции', 'fill_primer_field1', 'primer_page', 'section_id' );
	add_settings_field('primer_field2', 'Другая опция', 'fill_primer_field2', 'primer_page', 'section_id' );
}

## Заполняем опцию 1
function fill_primer_field1(){
	$val = get_option('option_name');
	$val = $val ? $val['input'] : null;
	?>
	<input type="text" name="option_name[input]" value="<?php echo esc_attr( $val ) ?>" />
	<?php
}

## Заполняем опцию 2
function fill_primer_field2(){
	$val = get_option('option_name');
	$val = $val ? $val['checkbox'] : null;
	?>
	<label><input type="checkbox" name="option_name[checkbox]" value="1" <?php checked( 1, $val ) ?> /> отметить</label>
	<?php
}

## Очистка данных
function sanitize_callback( $options ){ 
	// очищаем
	foreach( $options as $name => & $val ){
		if( $name == 'input' )
			$val = strip_tags( $val );

		if( $name == 'checkbox' )
			$val = intval( $val );
	}

	//die(print_r( $options )); // Array ( [input] => aaaa [checkbox] => 1 )

	return $options;
}

В итоге получим такую страницу:

primer
Теперь давайте разберем код по порядку, от общего к частному...

Чтобы быстро усвоить принцип надо мыслить категориями, а не переменными...

Категория 1: Создание страницы настроек

Регистрируем страницу настроек другой функцией не относящийся к API настроек:

add_options_page( 'Настройки Primer', 'Primer', 'manage_options', 'primer_slug', 'primer_options_page_output' );
  • 'primer_slug' - это ярлык страницы настроек и он по сути в API настроек нигде не фигурирует...
Категория 2: Вывод секции на странице настроек

Страница настроек есть, теперь на ней нам нужно вызвать секцию с настройками. Самой секции пока нет и в ней тоже ничего нет. Секцию и её содержимое мы создадим чуть ниже:

        <form action="options.php" method="POST">
			<?php
			settings_fields( 'option_group' );     // скрытые защитные поля
			do_settings_sections( 'primer_page' ); // секции с настройками (опциями). У нас она всего одна 'section_id'
			submit_button();
			?>
		</form>
Категория 3: Регистрация/создание секции
add_settings_section( 'section_id', 'Основные настройки', '', 'primer_page' );
  • 'section_id' - чтобы к этой секции потом добавить поля
  • 'primer_page' - привязывает эту секцию к выводу секции do_settings_sections( 'primer_page' );
Категория 4: Заполнение секции опциями
    add_settings_field('primer_field1', 'Название опции', 'fill_primer_field1', 'primer_page', 'section_id' );
	add_settings_field('primer_field2', 'Другая опция', 'fill_primer_field2', 'primer_page', 'section_id' );
  • 'section_id' - добавляет поле в секцию.
  • 'primer_page' - дополнительное уточнение, что поле нужно добавить в секцию, которая вызывается с параметром do_settings_sections( 'primer_page' );.
Категория 5: Регистрация самой настройки

Сейчас у нас уже полностью готов весь вывод настроек, но сохранение не работает, потому что WordPress не знает о существовании новой опции. Нужно «сказать» WordPress, что есть настройка option_name и её нужно обрабатывать.

register_setting( 'option_group', 'option_name', 'sanitize_callback' );
  • 'option_group' - нужно для вывода скрытых полей, для защиты формы. Для settings_fields( 'option_group' );

  • 'option_name' - название самой опции, которая будет записываться в таблицу wp_options

  • 'sanitize_callback' - функция для изменения/очистки передаваемых данных. Её можно не указывать, тогда данные сохраняться как есть (как передаются).
API настроек (опций) 57 комментариев
Полезные 6 Вопросы 4 Все
  • Shum

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

    Ответить4 месяца назад #
  • Цифровой cайт: digital-boom.ru @

    Пытаюсь воплотить в жизнь этот код и пока что-то не получается. Хотелось бы подробного объяснения этой вот части

    function fill_primer_field1(){
    	$val = get_option('option_name');
    	$val = $val['input'];
    	?>
    	<input type="text" name="option_name[input]" value="<?php echo esc_attr( $val ) ?>" />
    	<?php
    }

    как она должна выглядеть, если у меня группы полей, например 3 текстовых поля в одной группе. Интерпретатор ругается вот на эту строку:

    $val = $val['input'];

    Ответить2 месяца назад #
    • campusboy1946 cайт: www.youtube.com/c/wpplus @

      Посмотри, что содержит переменная $val после получения данных и станет понятно.

      Ответить2 месяца назад #
      • Цифровой cайт: digital-boom.ru @

        Не получается получить к ней доступ. Выдает ошибку и при выводе в консоль и при алерте. Данные вообще не записываются в БД. В БД создается запись с именем поля, но она пустая.

        Ответить2 месяца назад #
    • апож

      $val = $val['input']
      похоже на попытку перевода строки в массив, если выдает ошибку значит не получилось, просто удалите это и все должно заработать

      Ответить2 месяца назад #
    • Kama4659

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

      Ответитьмесяц назад #

Здравствуйте, !

Ваш комментарий