Using the WordPress Settings API

The WordPress Settings API can be used by plugins and themes to easily create settings pages. The API lets you create settings fields and assign them to a form. The API handles the form submission. This is a really great developer helper, and it was added in WordPress 2.7.

I was working on a plugin recently that needed to have a settings page. So, I took a look at the Settings API in the WordPress Codex. Then I looked at the various tutorials on it. In short, I couldn’t find anything that really explained it in simple terms. It took me a while to figure out exactly what groups and sections and fields were. The problem was that there were no illustrations, or detailed explanations of exactly what was going on. The example code wasn’t always that great either, and was hard to follow.

This my be a unique experience, and maybe others catch onto the API much quicker. But for those like me who are looking for a little bit better documentation, here it is. A complete working sample is at the bottom of the page. Enjoy!

Creating an Options Page #

If you are using the Settings API, you are might be thinking of creating a new settings page. Actually, that isn’t necessary, and if your settings fit in somewhere on one of the preexisting options pages, you might want to consider just putting them here instead. But in many cases, that really doesn’t make sense. So here is how to create your own settings or options page.

For this, you can use the add_options_page() function. (If you don’t want your options page under the settings menu, then you will want to use the add_menu_page() or add_submenu_page() functions instead.) The function takes 5 parameters, which are illustrated below.

  1. The page title (shown in the browser title bar, etc.).
  2. The menu title (shown in the menu).
  3. The minimum capability required to access the page (you will probably want to use 'manage_options').
  4. The page slug.
  5. The name of the function that will output the page’s contents.

The code might look something like this:

/** Add Settings Page **/
function myplugin_settings_menu() {

	add_options_page(
	/*1*/	'My Plugin Settings',
	/*2*/	'My Plugin',
	/*3*/	'manage_options',
	/*4*/	'myplugin_settings',
	/*5*/	'myplugin_settings_page'
	);

}
add_action( 'admin_menu', 'myplugin_settings_menu' );

As you can see, we need to hook this function to the 'admin_menu' action.

settings-api-1

The function that displays the page’s contents (outlined in blue above), might look something like this:

<?php

/** Settings Page Content **/
function myplugin_settings_page() {

	?>

	<div class="wrap">
		<?php 
		
		// Uncomment if this screen isn't added with add_options_page() 
		// settings_errors(); 
		
		?>

		<h2>My Plugin</h2>
		<p>Some text describing what the plugin settings do.</p>

		<form method="post" action="options.php">
			<?php

			// Output the settings sections.
			do_settings_sections( 'myplugin_settings' );

			// Output the hidden fields, nonce, etc.
			settings_fields( 'myplugin_settings_group' );

			// Submit button.
			submit_button();

			?>
		</form>
	</div>

	<?php
}

?>

This function creates a form, inside of which we call several functions. As you can see, the form will POST its data to the options.php page. This is important, because unless you set the action to point to options.php, your data wont automatically be saved. Don’t worry though, this doesn’t mean that you have to use the API only on admin screens registered as sub-menus of the options page; after the data is saved the user will be redirected back to wherever they started. And if you are using the Settings API on an admin screen that isn’t a child of the options admin screen, you’ll want to add a call to settings_errors() to the top of your screen, to display any errors (and, unintuitively, the success message when all goes well).

Within the form, we first call do_settings_sections(), which displays the settings sections which I’ll show you the code for in a moment (see image below). Then we call settings_fields(), which adds some hidden fields (called an options group) to go along with our sections (we’ll talk about this more a little later, too). Then we add a submit button, with the aptly named submit_button() function.

settings-api-2

Option Groups #

An option group is just a group of options. When you create a new settings field (see below), you have to add it to an options group. That field will be ignored, unless it is submitted as part of that group. The option group is defined by some hidden fields in the form, which look something like this:

<input type="hidden" value="myplugin_settings_group" name="option_page"></input>
<input type="hidden" value="update" name="action"></input>
<input id="_wpnonce" type="hidden" value="ec6732adff" name="_wpnonce"></input>
<input type="hidden" value="/wp-admin/options-general.php?page=myplugin_settings" name="_wp_http_referer"></input>

The hidden fields for a particular group are added to a form using the settings_fields() function. The parameter for this function is the group’s name.

settings_fields( 'myplugin_settings_group' );

When an option is updated, WordPress checks to make sure that it was submitted along with the group it is registered with.

Creating Sections #

A section, as you can see in the images, is a group of input fields under a heading and some text.

If you are creating your own settings page, then you will need to add sections to it. (If you are just adding some options to a preexisting page, then you may just want to add your fields (see below) to a section that already exists on that page.)

The setting sections registered with a page are displayed by calling the do_settings_sections() function. All of the setting sections registered with that page will be displayed.

do_settings_sections( 'myplugin_settings' );

The add_settings_section() function is the one used to add a settings section to a page. It takes four parameters:

  1. The sections slug.
  2. The section’s title.
  3. The name of the function that will display the section’s content.
  4. The page to display the section on.

The code might look something like this:

add_settings_section(
	/*1*/	'myplugin_settings_section_1',
	/*2*/	'Section 1',
	/*3*/	'myplugin_settings_section_1_callback',
	/*4*/	'myplugin_settings'
);

The result of that on the page is illustrated below (the second section was added in the same way).

settings-api-3

The callback function (parameter 3) is fired right below the section heading. You can use that to add an explanation of what the section’s settings do, etc.

function myplugin_settings_section_1_callback() {

	echo( 'Some info about this section.' );
}

Adding Fields #

A settings field is just a form field. It gets assigned to a particular section on a particular page, and registered with a particular group. The add_settings_field() function is the one that adds a settings field to a particular section and page. It takes five parameters:

  1. The field’s slug.
  2. The text of the field’s form label.
  3. The name of the function to use to generate the form field.
  4. The page to display the field on.
  5. The section to display the field under.

The code would look something like this:

add_settings_field(
	/*1*/	'myplugin_field_1',
	/*2*/	'Field 1',
	/*3*/	'myplugin_field_1_input',
	/*4*/	'myplugin_settings',
	/*5*/	'myplugin_settings_section_1'
);

We also need to create an option in the database to hold the default value of this settings field. It will automatically be updated by WordPress when the setting is updated. That’s the great thing about the Settings API!) You can do that with add_option():

add_option( 'myplugin_field_1', 'the default value for this field' );

As you can see, the first parameter is the field’s slug, the second is the value you want it to have.

We also need our function to display the field (parameter 3 of add_settings_field()). It would look like this:

function myplugin_field_1_input() {
	
	echo( '<input type="text" name="myplugin_field_1" id="myplugin_field_1" value="'. get_option( 'myplugini_field_1' ) .'" />' );
}

In this case we are creating a text input. The name and id attributes need to match the setting field’s slug. We assign the current value of that option to the value attribute, so we know what the current setting is.

If we added two more fields, our page might look something like this:

settings-api-4

But we still need to register our new field with a settings group, or else WordPress won’t recognize it when the settings are updated. The function to do that is register_setting():

register_setting( 'myplugin_settings_group', 'myplugin_field_1' );

As you can see, it takes only two parameters:

  1. The name of the group we want to register the field with.
  2. The name of the field.

Putting it all together #

When we put all the code together, and add in the code for the other section and two more fields, it will look something like the code shown below.

<?php

/** Set Defaults **/
add_option( 'myplugin_field_1', 'some default value' );
add_option( 'myplugin_field_2', '1' );
add_option( 'myplugin_field_3', 'another default value' );

/** Add Settings Page **/
function myplugin_settings_menu() {

	add_options_page(
	/*1*/	'My Plugin Settings',
	/*2*/	'My Plugin',
	/*3*/	'manage_options',
	/*4*/	'myplugin_settings',
	/*5*/	'myplugin_settings_page'
	);

}
add_action( 'admin_menu', 'myplugin_settings_menu' );

<?php

/** Settings Page Content **/
function myplugin_settings_page() {

	?>

	<div class="wrap">
		<?php 
		
		// Uncomment if this screen isn't added with add_options_page() 
		// settings_errors(); 
		
		?>

		<h2>My Plugin</h2>
		<p>Some text describing what the plugin settings do.</p>

		<form method="post" action="options.php">
			<?php

			// Output the settings sections.
			do_settings_sections( 'myplugin_settings' );

			// Output the hidden fields, nonce, etc.
			settings_fields( 'myplugin_settings_group' );

			// Submit button.
			submit_button();

			?>
		</form>
	</div>

	<?php
}

/** Settings Initialization **/
function myplugin_settings_init() {

     /** Setting section 1. **/
	add_settings_section(
	/*1*/	'myplugin_settings_section_1',
	/*2*/	'Section 1',
	/*3*/	'myplugin_settings_section_1_callback',
	/*4*/	'myplugin_settings'
	);
	
	// Field 1.
	add_settings_field(
	/*1*/	'myplugin_field_1',
	/*2*/	'Field 1',
	/*3*/	'myplugin_field_1_input',
	/*4*/	'myplugin_settings',
	/*5*/	'myplugin_settings_section_1'
	);

	// Register this field with our settings group.
	register_setting( 'myplugin_settings_group', 'myplugin_field_1' );
	
   /** Section 2 **/
	add_settings_section(
	/*1*/	'myplugin_settings_section_2',
	/*2*/	'Section 2',
	/*3*/	'myplugin_settings_section_2_callback',
	/*4*/	'myplugin_settings'
	);
	
	// Field 2.
	add_settings_field(
	/*1*/	'myplugin_field_2',
	/*2*/	'Field 2',
	/*3*/	'myplugin_field_2_input',
	/*4*/	'myplugin_settings',
	/*5*/	'myplugin_settings_section_2'
	);

	// Register this field with our settings group.
	register_setting( 'myplugin_settings_group', 'myplugin_field_2' );	
	
	// Field 3.
	add_settings_field(
	/*1*/	'myplugin_field_3',
	/*2*/	'Field 3',
	/*3*/	'myplugin_field_3_input',
	/*4*/	'myplugin_settings',
	/*5*/	'myplugin_settings_section_2'
	);

	// Register this field with our settings group.
	register_setting( 'myplugin_settings_group', 'myplugin_field_3' );
}
add_action( 'admin_init', 'myplugin_settings_init' );

function myplugin_settings_section_1_callback() {

	echo( 'Some info about this section.' );
}

function myplugin_settings_section_2_callback() {

	echo( 'An explanation of this section.' );
}

/** Field 1 Input **/
function myplugin_field_1_input() {

	echo( '<input type="text" name="myplugin_field_1" id="myplugin_field_1" value="'. get_option( 'myplugini_field_1' ) .'" />' );
}

/** Field 2 Input **/
function myplugin_field_2_input() {

	// This example input will be a dropdown.
	// Available options.
	$options = array(
		'1' => 'Option 1',
		'2' => 'Option 2',
		'3' => 'Option 3',
	);
	
	// Current setting.
	$current = get_option( 'myplugin_field_2' );
	
	// Build <select> element.
	$html = '<select id="myplugin_field_2" name="myplugin_field_2">';

	foreach ( $options as $value => $text )
	{
		$html .= '<option value="'. $value .'"';

		// We make sure the current options selected.
		if ( $value == $current ) $html .= ' selected="selected"';

		$html .= '>'. $text .'</option>';
	}
	
	$html .= '</select>';

	echo( $html );	
}

/** Field 3 Input **/
function myplugin_field_3_input() {

	// Output the form input, with the current setting as the value.
	echo( '<input type="text" name="myplugin_field_3" id="myplugin_field_3" value="'. get_option( 'myplugin_field_3' ) .'" />' );	
}

?>

This is the code used to generate the example page shown in the images. Feel free to copy it, and modify it to fit your needs.

I hope you have found this tutorial helpful. If you have any comments, please leave them below.

7 thoughts on “Using the WordPress Settings API

  1. ClockwiseQ

    This is the best tutorial (walk-through) I have read YET for the Settings API. Thank you so much for putting this together. It solved an issue i was struggling with.

    Reply
  2. Paul WIlliamson

    Agreed, having read a whole bunch of tutorials regarding the WordPress Settings API – found this to be a great resource.

    What makes it for me is the visualization of the various ‘parts’ that make up the API – there really should be more of this sort of thing!

    Thanks

    Reply
  3. darvy

    this is a great tutorial, thanks for the article, there is a third parameter in register_setting think it is to validate data, please could you make a short explanation about that too

    Reply
    1. J.D. Grimes Post author

      You are correct, there is a third parameter for register_setting() that relates to sanitizing the data. All settings/options are passed through the "sanitze_option_{$option_name}" filter before being saved to the database. Passing a function name as the third parameter will cause it to be automatically hooked to the filter for that setting’s option. So, if you have an option that should always be a positive integer, you could have it sanitized with the absint() function by passing 'absint' as the third parameter when registering the setting. For more sophisticated sanitization you could create your own functions as well.

      Reply
  4. Masud

    The way you explained Setting API easily in plain English is really amazing! Thanks a lot! Very helpful article :)

    Reply
  5. paul

    Thank you so much. you made understanding of the wordpress settings API as simple as ABC! Thanks a million time.

    Reply

Leave a Reply to paul Cancel reply

Your email address will not be published. Required fields are marked *