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

register_setting()WP 2.7.0

Регистрирует новую опцию и callback функцию для обработки значения опции при её сохранении в БД.

Эта функция также может использоваться для регистрации новой опции, которая будет добавлена на базовую страницу настроек WordPress (Общие, Медиафайлы, Чтение...) и в REST API. Опция добавляется в существующую секцию при помощи функции add_settings_field() или можно создать новую секцию функцией add_settings_section() и добавить опцию туда.

Функцию нужно вызывать на хуке:

  • admin_init - для использования через интерфейс админки.
  • rest_api_init - для использования в REST API. Для этого нужно указать параметр show_in_rest=true. См. примеры ниже.
При первом добавлении опции в БД очистка срабатывает два раза.

Например, следующая функция вернет строку с двумя восклицательными знаками:

function append_exclamation( $input ){ return $input .'!'; }

В этом случае, скорее всего, опции еще не существует в таблице wp_options, поэтому функция update_option() "увидев", что такой опции нет, вызывает add_option(), чтобы добавить новую опцию. Так получается потому что хук sanitize_option вызывается до вызова функции add_option() и срабатывает второй раз, уже внутри add_option().

Ошибка: ERROR: options page not found - объяснение и решение проблемы:

Такая ошибка возникает, когда фильтр whitelist_options ничего не знает о вашей новой опции.

register_settings() добавляет данные в глобальную переменную $new_allowed_options. Затем эта переменная объединяется с переменной $whitelist_options в option_update_filter(), которая в свою очередь добавляет новые данные в $new_allowed_options, где $option_group - используется как индекс новых данных. Когда вы получаете ошибку "ERROR: options page not found" - это означает, что не удалось найти опции по ключу.

ЗАМЕТКА: До версии 5.5 опция $new_allowed_options называлась $new_whitelist_options.

Путаница получается, потому что первый аргумент $options_group используется как ключ, а реальное сравнение в файле options.php происходит с параметром $options_page, который равен $hook_suffix, получаемый из результата работы функции add_submenu_page().

Простое решение этой проблемы, указывать одинаковые названия для параметров $option_group и $option_name.

Другая причина этой ошибки - когда неправильно указан параметр $page при вызове функции:

add_settings_section( $id, $title, $callback, $page )

или

add_settings_field( $id, $title, $callback, $page, $section, $args )

Заметка: $page должен быть равен $menu_slug из функции:

add_theme_page( $page_title, $menu_title, $capability, $menu_slug, $function );

Используется в связке с другими функциями API настроек:

Хуки из функции

Возвращает

null. Ничего не возвращает.

Использование

register_setting( $option_group, $option_name, $args );
$option_group(строка) (обязательный)
Название группы, к которой будет принадлежать опция. Это название должно совпадать с названием группы в функции settings_fields().
$option_name(строка) (обязательный)
Название опции, которая будет сохраняться в БД.
$args(массив/строка)

Данные регистрируемой опции (с версии 4.7).

До версии 4.7. тут указывалась коллбэк функция: sanitize_callback, т.е. нужно было указывать строку - название функции, а теперь эта строка указывается в одноименном элементе массива. Прошлый вариант поддерживается, т.е. есть обратная совместимость.

Если опцию не планируется использовать в REST API, то можно указать только два элемента массива sanitize_callback и default.

$defaults = array(
	'sanitize_callback' => null,
	'default'           => null,
	'type'              => 'string',
	'group'             => $option_group,
	'description'       => '',
	'show_in_rest'      => false,
);
  • sanitize_callback(строка/массив)
    Название функции обратного вызова, которая будет обрабатывать значение опции перед сохранением.

    Важно! Функция получит один параметр - значение опции. Значение которое указанная функция вернет, будет записано в опцию.

  • default(разное)
    Значение по умолчанию при вызове get_option().

    Влияет как на Options API (например, get_option()), так и на REST API.

  • type(строка) (REST API)
    Тип данных с которыми опция ассоциирована. Возможные значения 'string', 'boolean', 'integer', 'number', 'array', 'object'.

    Используется только в REST API для определения схемы и применения соответствующей очистки (sanitization).

    Имеет смысл только если show_in_rest=true. Поэтому при show_in_rest=false или когда параметр не установлен, параметр можно не указывать.

    Не влияет на работу страниц админки или на то, как настройка обрабатывается в API опций. (Т.е., например, можно установить type=boolean и в форме при сохранении этой опции передать строку - через админ-панель указанная строка сохранится в БД. Но в REST API при таком варианте будет ошибка.

  • description(строка) (REST API)
    Описание данных, которые будут храниться в этой опции.

    Используется только в REST API, поэтому имеет смысл только если show_in_rest=true.

  • show_in_rest(логический|массив) (REST API)
    Нужно ли добавлять данные этой опции в REST API.

    При регистрации сложных настроек этот аргумент может быть массивом в котором можно использовать ключ schema.

По умолчанию: array()

Примеры

1

#1 Пример показывающий как нужно подключать функцию через хук admin_init:

add_action( 'admin_init', 'register_my_setting' );
function register_my_setting() {
	register_setting( 'my_options_group', 'my_option_name', 'intval' ); 
} 
0

#2 Другие примеры

Еще примеры смотрите в описании API опций.

0

#3 Регистрация опции (текстовое поле), также и для REST API

Если регистрация делается и для сайта и для REST API, то вызов функции нужно повесить на оба хука rest_api_init и admin_init. Если использовать только хук admin_init то в REST опция работать не будет.

В этом случае опцию также можно будет видеть при обращениях к эндпоинту wp-json/wp/v2/settings.

add_action( 'admin_init', 'register_my_setting' );
add_action( 'rest_api_init', 'register_my_setting' );

function register_my_setting() {

	$args = array(
		'sanitize_callback' => 'sanitize_text_field',
		'default'      => '',
		'type'         => 'string',
		'show_in_rest' => true,
	);

	register_setting( 'my_options_group', 'my_option_name', $args ); 
} 
0

#4 Регистрация опции только для REST API

add_action( 'rest_api_init', 'register_block_core_site_logo_setting', 10 );

/**
 * Register a core site setting for a site logo
 */
function register_block_core_site_logo_setting() {

	register_setting( 'general', 'site_logo', [
		'show_in_rest' => array(
			'name' => 'site_logo',
		),
		'type'         => 'integer',
		'description'  => __( 'Site logo.' ),
	] );
}
0

#5 Опция типа массив в REST API

Если вы хотите сохранить массив в настройках, а также показать этот массив в конечной точке wp-json/wp/v2/settings, то нужно указать схему массива в параметре show_in_rest.

add_action( 'admin_init',    'wpdocs_foo_register_settings' );
add_action( 'rest_api_init', 'wpdocs_foo_register_settings' );

function wpdocs_foo_register_settings() {

	register_setting( 'general_setting', 'id' );
	register_setting( 'general_setting', 'order' );
	register_setting(
		'general_setting',
		'slider-data',
		array(
			'show_in_rest' => array(
				'name' => 'images_slide',
				'schema' => array(
					'type'  => 'array',
					'items' => array(
						'id'    => 'string',
						'order' => 'string',
					),
				),
			),
			'type' => 'array',
			'sanitize_callback' => array( $this, 'wpdocs_admin_post_save_data' ),
		)
	);
}
0

#6 Пример для типов object и array:

register_setting(
	'dp_example_settings_group',
	'dp_example_array_settings',
	array(
		'type'         => 'object',
		'default'      => array(
			'A',
			'B',
			'C',
		),
		'show_in_rest' => array(
			'schema' => array(
				'type'  => 'object',
				'items' => array(
					'type' => 'string',
				),
			),
		),
	)
);

register_setting(
	'dp_example_settings_group',
	'dp_example_object_settings',
	array(
		'type'         => 'object',
		'default'      => array(
			'some_str' => 'A',
			'some_int' => 3,
		),
		'show_in_rest' => array(
			'schema' => array(
				'type'       => 'object',
				'properties' => array(
					'some_str' => array(
						'type' => 'string',
					),
					'some_int' => array(
						'type' => 'integer',
					),
				),
			),
		),
	)
);
-1

#7 Обработка, когда sanitize срабатывает дважды

Как упоминалось в заметке выше sanitize может сработать два раза, когда опция первый раз добавляется в БД. Поэтому, если есть какие-либо критические по производительности моменты или другие моменты, которые нужно учесть в этом случае, то их нужно отдельно обработать в sanitize функции.

add_action( 'admin_init', 'on_admin_init' );

/*
 *  Add custom options to whitelist, allowing valiated settings to be saved by form.
 */
function on_admin_init(): void 
{
	register_setting( PLUGIN_SLUG, PLUGIN_SLUG, [ 'sanitize_callback' => 'my_sanitize_settings' ] ); 
}

/*
 *  Sanitize the form input.
 */
function my_sanitize_settings( $input = NULL ):  
{
	// Detect multiple sanitizing passes.
	// Accomodates bug: https://core.trac.wordpress.org/ticket/21989
	static $pass_count = 0; $pass_count++;

	if ( $pass_count <= 1 ) {
		// Handle any single-time / performane sensitive actions.

	}

	// Insert regular santizing code here.
}

Функция срабатывает дважды только при первом сохранении настройки и добавлении ее в таблицу в базе данных. Последующие обновления настройки выполняют функцию sanitize_callback только один раз. Так что если вы не выполняете какую-то очень-очень-очень тяжелую операцию по очистке, нет необходимости беспокоиться об этом.

Заметки

  • Global. Массив. $new_allowed_options
  • Global. Массив. $wp_registered_settings

Список изменений

С версии 2.7.0 Введена.
С версии 3.0.0 The misc option group was deprecated.
С версии 3.5.0 The privacy option group was deprecated.
С версии 4.7.0 $args can be passed to set flags on the setting, similar to register_meta().
С версии 5.5.0 $new_whitelist_options was renamed to $new_allowed_options. Please consider writing more inclusive code.

Код register_setting() WP 6.1.1

function register_setting( $option_group, $option_name, $args = array() ) {
	global $new_allowed_options, $wp_registered_settings;

	/*
	 * In 5.5.0, the `$new_whitelist_options` global variable was renamed to `$new_allowed_options`.
	 * Please consider writing more inclusive code.
	 */
	$GLOBALS['new_whitelist_options'] = &$new_allowed_options;

	$defaults = array(
		'type'              => 'string',
		'group'             => $option_group,
		'description'       => '',
		'sanitize_callback' => null,
		'show_in_rest'      => false,
	);

	// Back-compat: old sanitize callback is added.
	if ( is_callable( $args ) ) {
		$args = array(
			'sanitize_callback' => $args,
		);
	}

	/**
	 * Filters the registration arguments when registering a setting.
	 *
	 * @since 4.7.0
	 *
	 * @param array  $args         Array of setting registration arguments.
	 * @param array  $defaults     Array of default arguments.
	 * @param string $option_group Setting group.
	 * @param string $option_name  Setting name.
	 */
	$args = apply_filters( 'register_setting_args', $args, $defaults, $option_group, $option_name );

	$args = wp_parse_args( $args, $defaults );

	// Require an item schema when registering settings with an array type.
	if ( false !== $args['show_in_rest'] && 'array' === $args['type'] && ( ! is_array( $args['show_in_rest'] ) || ! isset( $args['show_in_rest']['schema']['items'] ) ) ) {
		_doing_it_wrong( __FUNCTION__, __( 'When registering an "array" setting to show in the REST API, you must specify the schema for each array item in "show_in_rest.schema.items".' ), '5.4.0' );
	}

	if ( ! is_array( $wp_registered_settings ) ) {
		$wp_registered_settings = array();
	}

	if ( 'misc' === $option_group ) {
		_deprecated_argument(
			__FUNCTION__,
			'3.0.0',
			sprintf(
				/* translators: %s: misc */
				__( 'The "%s" options group has been removed. Use another settings group.' ),
				'misc'
			)
		);
		$option_group = 'general';
	}

	if ( 'privacy' === $option_group ) {
		_deprecated_argument(
			__FUNCTION__,
			'3.5.0',
			sprintf(
				/* translators: %s: privacy */
				__( 'The "%s" options group has been removed. Use another settings group.' ),
				'privacy'
			)
		);
		$option_group = 'reading';
	}

	$new_allowed_options[ $option_group ][] = $option_name;

	if ( ! empty( $args['sanitize_callback'] ) ) {
		add_filter( "sanitize_option_{$option_name}", $args['sanitize_callback'] );
	}
	if ( array_key_exists( 'default', $args ) ) {
		add_filter( "default_option_{$option_name}", 'filter_default_option', 10, 3 );
	}

	/**
	 * Fires immediately before the setting is registered but after its filters are in place.
	 *
	 * @since 5.5.0
	 *
	 * @param string $option_group Setting group.
	 * @param string $option_name  Setting name.
	 * @param array  $args         Array of setting registration arguments.
	 */
	do_action( 'register_setting', $option_group, $option_name, $args );

	$wp_registered_settings[ $option_name ] = $args;
}
8 комментариев
    Войти