API Settings (Options)

The options API was added in version 2.7 and allows you to create form fields to save settings. The API automates the saving of options in the database and outputs the necessary HTML code on the screen. This approach allows for the convenient addition of your own options and option sections to existing settings pages (General, Reading, Media, etc.). Alternatively, you can create plugin settings pages without using unnecessary code.

Despite all the conveniences, registration and validation (sanitization) of field values have not gone anywhere - all of this needs to be done manually.

Note: All POST requests with form data must be sent to the page wp-admin/options.php. Users must have the manage_options capability. In multisite versions, they must be Super Admins to submit form data.

All option registration functions: register_setting(), add_settings_*() etc. must be called on the admin_init hook.

Functions of the Settings API

Registering/Unregistering Options
Adding Sections and Individual Fields
Output to Screen
Errors

Adding Option Fields

A new option field can be added to a section on an existing WordPress options page or on a plugin options page. This is done using the add_settings_field() function.

The callback function must output the HTML code for the field (input, textarea, ...). WordPress will take care of saving the option to the database. Typically, data is saved in the wp_options table, but it can be reconfigured.

The option being added must first be registered with the register_setting() function; otherwise, it will not be saved or updated.

add_settings_field( $id, $title, $callback, $page, $section = 'default', $args = array() );
  • $id - The slug of the option, used as the field identifier. Used in the ID attribute of the tag.

  • $title - The title of the field.

  • $callback - The name of the callback function. The function should fill the field with the necessary <input> tag, which will be part of one large form. The name attribute must equal the $option_name parameter from register_setting(). The id attribute usually equals the $id parameter. The result should be immediately output to the screen (echo).

  • $page - The menu page where the field will be added. You should specify the slug of the page, i.e., the parameter must equal the $menu_slug parameter from add_theme_page(). For the basic WordPress pages, the names are: general, reading, writing, etc., by analogy...

  • $section - The title of the settings page section to which the field should be added. By default, it is default or may be a section added by the add_settings_section function.

  • $args - Additional parameters that should be passed to the callback function.

Adding Option Sections

Option sections are blocks of options highlighted by a title. Instead of creating a new settings page, it is sometimes wiser to add a new section to an existing WordPress settings page - this will make the plugin simpler and WordPress will not be burdened with a new settings page for the plugin.

add_settings_section( $id, $title, $callback, $page );
  • $id - The identifier of the section. Fields are attached to this ID (see add_settings_field()).

  • $title - The title of the section (the name of the block).

  • $callback - The callback function that is executed at the beginning of the section, before the fields are output. In it, you can output text describing the section; it should be output immediately to the screen using echo.

  • $page - The type of settings page on which the section will be displayed (general, reading, writing, ...).

Registering Options

register_setting( $option_group, $option_name, $sanitize_callback );
unregister_setting( $option_group, $option_name, $sanitize_callback );
  • $option_group - The name of the group to which the option belongs. It must match the group in the settings_fields() function.

  • $option_name - The name of the option that will be saved.

  • $sanitize_callback - The callback function that will process the value before saving.

Outputting Option Sections to the Screen

When the API is used to add options to an existing options page, there is no need to worry about the HTML tag of the form itself, because it is already added to the page, and the options (input fields) will be inserted inside this form. However, when you create a new options page, you need to specify the HTML form tag (form) and its structure.

settings_fields

To output hidden fields and ensure the security of the options form data, use the settings_fields() function: settings_fields( $option_group );

  • $option_group - The name of the group. It must match the same parameter in register_setting(). This is the name of the page (its slug) on which the options are displayed.
do_settings_sections

To output the section intended for the options page, you need to use the do_settings_sections() function: do_settings_sections( $page );

  • $page - An alternative name (slug) of the page of the section to be displayed. It must match the name of the page in the add_settings_section() function.

The do_settings_fields() function is similar to do_settings_sections(); it also outputs fields for a specific page and section, but these fields are not formatted in a tabular view and are output as they are. Usually, there is no need to call this function directly; you should use do_settings_sections() to output option fields related to the section.

submit_button

The options form needs a submit button. For this, use the submit_button() function.

Outputting the Entire Form Block

Finally, you will need to add the HTML tag

specifying the attributes action="options.php" method="POST". This example shows how to correctly output a form for a separate options page, using previously registered fields:

<form method="POST" action="options.php">
	<?php
	settings_fields( 'my-page' );  // name of the options group - register_setting( $option_group )
	do_settings_sections( 'my-page' ); // slug of the page on which the form is displayed
	submit_button();
	?>
</form>

Examples

#1. Additional Options on the WordPress "Reading" Settings Page

Let's add a new section with two new options to the basic WordPress "Reading" settings page.

// register all options, sections, fields on the admin_init hook
add_action( 'admin_init', 'eg_settings_api_init' );

function eg_settings_api_init() {

	// Add an options block to the basic "Reading" page
	add_settings_section(
		'eg_setting_section', // section
		'Title for settings section',
		'eg_setting_section_callback_function',
		'reading' // page
	);

	// Add option fields. Specify the name, description,
	// function that outputs the HTML code.
	add_settings_field(
		'eg_setting_name',
		'Description of the option field',
		'eg_setting_callback_function', // can specify ''
		'reading', // page
		'eg_setting_section' // section
	);
	add_settings_field(
		'eg_setting_name2',
		'Description of the option field2',
		'eg_setting_callback_function2',
		'reading', // page
		'eg_setting_section' // section
	);

	// Register options so they are saved when sending
	// $_POST parameters and so that the option callback functions output their values.
	register_setting( 'reading', 'eg_setting_name' );
	register_setting( 'reading', 'eg_setting_name2' );
}

/**
 * Callback function for the section.
 *
 * The function is triggered at the beginning of the section; if no text needs to be output or
 * anything else done before outputting options,
 * then the function can be omitted by specifying '' in the third
 * parameter of add_settings_section.
 *
 * @return void
 */
function eg_setting_section_callback_function() {
	echo '<p>Text describing the settings block</p>';
}

/**
 * Callback functions outputting the HTML code for options.
 *
 * Create checkbox and text input tags.
 *
 * @return void
 */
function eg_setting_callback_function() {
	?>
	<input
		name="eg_setting_name"
		type="checkbox"
		<?php checked( 1, get_option( 'eg_setting_name' ) ) ?>
		value="1"
		class="code"
	/>
	<?php
}

function eg_setting_callback_function2() {
	?>
	<input
		name="eg_setting_name2"
		type="text"
		value="<?php echo esc_attr( get_option( 'eg_setting_name2' ) ); ?>"
		class="code2"
	 />
	<?php
}

Resulted in:

#2. Plugin Settings Page (options in an array)

Let's create a plugin that will only have a settings page. We will do this to understand how the settings API works.

Here, one option is registered, and several different options are added to it as an array of data. This is more convenient and practical.

<?php
/*
 * Plugin name: Primer
 * Description: Demonstration of creating a settings page for a plugin
*/

/**
 * Create the plugin settings page
 */
add_action( 'admin_menu', 'add_plugin_page' );

function add_plugin_page(){

	add_options_page(
		'Primer Settings',
		'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' );     // hidden security fields
				do_settings_sections( 'primer_page' ); // sections with settings (options). We have only one 'section_id'
				submit_button();
			?>
		</form>
	</div>
	<?php
}

/**
 * Register settings.
 * Settings will be stored in an array, not one setting = one option.
 */
add_action( 'admin_init', 'plugin_settings' );

function plugin_settings(){

	// parameters: $option_group, $option_name, $sanitize_callback
	register_setting( 'option_group', 'option_name', 'sanitize_callback' );

	// parameters: $id, $title, $callback, $page
	add_settings_section( 'section_id', 'Main Settings', '', 'primer_page' );

	// parameters: $id, $title, $callback, $page, $section, $args
	add_settings_field('primer_field1', 'Option Name', 'fill_primer_field1', 'primer_page', 'section_id' );
	add_settings_field('primer_field2', 'Another Option', 'fill_primer_field2', 'primer_page', 'section_id' );
}

// Fill option 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
}

// Fill option 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 ) ?> /> check</label>
	<?php
}

// Data sanitization
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;
}

As a result, we will get such a page:

Now, let's break down the code step by step.

1) Creating the Settings Page

We register the settings page using the function add_options_page() - it is not directly related to the settings API:

add_options_page( 'Primer Settings', 'Primer', 'manage_options', 'primer_slug', 'primer_options_page_output' );
  • primer_slug - this is the slug of the settings page and it does not appear anywhere in the settings API...
2) Outputting the Section on the Settings Page

The settings page is created, now we need to call the section with the settings on it. The section itself does not exist yet and it has nothing in it. We will create the section and its content a bit later:

<form action="options.php" method="POST">
	<?php
	settings_fields( 'option_group' );     // hidden security fields
	do_settings_sections( 'primer_page' ); // sections with settings (options). We have only one 'section_id'
	submit_button();
	?>
</form>
3) Registering/Creating the Section
add_settings_section( 'section_id', 'Main Settings', '', 'primer_page' );
  • section_id - to later add fields to this section
  • primer_page - links this section to the output of the section do_settings_sections( 'primer_page' );
4) Filling the Section with Options
add_settings_field('primer_field1', 'Option Name', 'fill_primer_field1', 'primer_page', 'section_id' );
add_settings_field('primer_field2', 'Another Option', 'fill_primer_field2', 'primer_page', 'section_id' );
  • section_id - adds the field to the section.
  • primer_page - an additional specification that the field should be added to the section called with the parameter do_settings_sections( 'primer_page' );.
5) Registering the Setting Itself

Now we have fully prepared the output of the settings, but saving does not work because WordPress does not know about the existence of the new option. We need to "tell" WordPress that there is a setting option_name and it needs to be processed.

register_setting( 'option_group', 'option_name', 'sanitize_callback' );
  • option_group - needed for outputting hidden fields for form protection. For settings_fields( 'option_group' );

  • option_name - the name of the option itself, which will be recorded in the wp_options table

  • sanitize_callback - function for modifying/sanitizing the passed data. It can be omitted, in which case the data will be saved as is (as passed).

#3. Phone Input Field

Let's add a phone input field to the "General Settings" page:

add_action( 'admin_init', 'phone_settings_api_init' );

function phone_settings_api_init() {
	register_setting( 'general', 'phone', 'sanitize_text_field' );

	add_settings_field(
		'phone',
		'<label for="phone">Phone</label>',
		'phone_field_html',
		'general'
	);
}

function phone_field_html() {
	$value = get_option( 'phone', '' );
	printf( '<input type="text" id="phone" name="phone" value="%s" />', esc_attr( $value ) );
}

We will output the saved phone on the screen in the desired location of the template:

echo esc_html( get_option( 'phone', '' ) );