WordPress.org

Ready to get started?Download WordPress

Codex

Attention Interested in functions, hooks, classes, or methods? Check out the new WordPress Code Reference!

Creating Options Pages

Introduction

Creating custom options panels in WordPress is relatively easy.

First, to create the menu item and the new page, see Adding Administration Menus.

So long as you stick to this structure, WordPress will handle all of the option creation, update, saving, and redirection for you. It will check permissions, and do all that other magic behind the scenes.

Several new functions were added in WordPress 2.7. These new functions are optional in WordPress 2.7 but will be required in the future. They are required for WordPress MU 2.7. See Migrating Plugins and Themes to 2.7 and Settings API for more information.

Opening the Page

You can either put the code for your options page in your plugin php file, or you can create a second file called options.php, for example, and include it using the php include function - http://www.w3schools.com/PHP/php_includes.asp

If you'd like to match the look and feel of existing WordPress options pages, open with the following:

<div class="wrap">
<h2>Your Plugin Page Title</h2>

Form Tag

Once you have your page, you need to create an HTML form. Use this code:

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

nonce Magic

Then after the opening form tag, insert this PHP code:

<?php wp_nonce_field('update-options'); ?>

This will insert two hidden fields which automatically help to check that the user can update options and also redirect the user back to the correct admin page (because the form action is a different page).

(This is not needed if the version 2.7 function settings_fields is used.)

Form Table

Most options pages use a table with the class "form-table" to display their options. To match the look and feel of these pages, create a new table:

<table class="form-table">

Use fields with the same names that you want your newly created options (stored in the options table) to be called, for example:

<tr valign="top">
<th scope="row">New Option Name</th>
<td><input type="text" name="new_option_name" value="<?php echo get_option('new_option_name'); ?>" /></td>
</tr>

A closer look at the <input> element:

<input type="text" name="new_option_name" value="<?php echo get_option('new_option_name'); ?>" />

Note that by using the get_option() function as the value for the field, this will automatically be updated when the options are saved.

Once you have added all your options rows, close the table:

</table>

action Field

Next, create a hidden field called action containing the value update.

<input type="hidden" name="action" value="update" />

(This is not needed if the version 2.7 function settings_fields is used.)

page_options Field

Finally, create a hidden field called page_options containing a comma separated list of all the options in the page that should be written on save.

<input type="hidden" name="page_options" value="new_option_name,some_other_option,option_etc" />

(This is not needed if the version 2.7 functions settings_fields and register_setting are used.)

Closing Tags

Then obviously close the form tag after your other options, and if you like, include another "Update Options" button, this is the WordPress default.

<p class="submit">
<input type="submit" class="button-primary" value="<?php _e('Save Changes') ?>" />
</p>
</form>
</div>

Note the use of the _e() function to handle translation of the text, see Localizing WordPress for more info.

See It All Together

<div class="wrap">
<h2>Your Plugin Name</h2>

<form method="post" action="options.php">
<?php wp_nonce_field('update-options'); ?>

<table class="form-table">

<tr valign="top">
<th scope="row">New Option Name</th>
<td><input type="text" name="new_option_name" value="<?php echo get_option('new_option_name'); ?>" /></td>
</tr>
 
<tr valign="top">
<th scope="row">Some Other Option</th>
<td><input type="text" name="some_other_option" value="<?php echo get_option('some_other_option'); ?>" /></td>
</tr>

<tr valign="top">
<th scope="row">Options, Etc.</th>
<td><input type="text" name="option_etc" value="<?php echo get_option('option_etc'); ?>" /></td>
</tr>

</table>

<input type="hidden" name="action" value="update" />
<input type="hidden" name="page_options" value="new_option_name,some_other_option,option_etc" />

<p class="submit">
<input type="submit" class="button-primary" value="<?php _e('Save Changes') ?>" />
</p>

</form>
</div>

Wordpress 2.7 and Newer

This function will create the options page.

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

Add sub menu page to the options main menu. This function takes a capability which will be used to determine whether or not a page is included in the menu. The function which is hooked in to handle the output of the page must check that the user has the required capability as well.

page_title
The text to be displayed in the title tags of the page when the menu is selected
menu_title
The text to be used for the menu
capability
The capability required for this menu to be displayed to the user.
menu_slug
The slug name to refer to this menu by (should be unique for this menu)
function
The function to be called to output the content for this page.


settings_fields Function

The setting fields will know which settings your options page will handle.

Somewhere within the form add this function

settings_fields( 'myoption-group' );

where myoption-group is the same name used in the register_setting function.

This function replaces the nonce magic, action field, and page_options field mentioned above.

Register Settings

The register_setting and unregister_setting functions add and remove options from a whitelist of allowed options that the form is able to save. They can also name a sanitize callback function as a security measure to check each option's value.

The register_setting function should be called in an admin_init action, which runs before every admin page and in particular, options.php, which receives this form.

Your plugin probably has a section with an add_action that adds a new menu item to the administration menus. This line will be in the same section to add an action to admin_init.

if ( is_admin() ){ // admin actions
  add_action( 'admin_menu', 'add_mymenu' );
  add_action( 'admin_init', 'register_mysettings' );
} else {
  // non-admin enqueues, actions, and filters
}

Then you create a new function that registers each option.

function register_mysettings() { // whitelist options
  register_setting( 'myoption-group', 'new_option_name' );
  register_setting( 'myoption-group', 'some_other_option' );
  register_setting( 'myoption-group', 'option_etc' );
}

The name of myoption-group doesn't matter but it has to match the name used in the settings_fields function above.


See It All Together

The below example uses the new Settings API to create and save your plugin options

<?php
// create custom plugin settings menu
add_action('admin_menu', 'baw_create_menu');

function baw_create_menu() {

	//create new top-level menu
	add_menu_page('BAW Plugin Settings', 'BAW Settings', 'administrator', __FILE__, 'baw_settings_page',plugins_url('/images/icon.png', __FILE__));

	//call register settings function
	add_action( 'admin_init', 'register_mysettings' );
}


function register_mysettings() {
	//register our settings
	register_setting( 'baw-settings-group', 'new_option_name' );
	register_setting( 'baw-settings-group', 'some_other_option' );
	register_setting( 'baw-settings-group', 'option_etc' );
}

function baw_settings_page() {
?>
<div class="wrap">
<h2>Your Plugin Name</h2>

<form method="post" action="options.php">
    <?php settings_fields( 'baw-settings-group' ); ?>
    <table class="form-table">
        <tr valign="top">
        <th scope="row">New Option Name</th>
        <td><input type="text" name="new_option_name" value="<?php echo get_option('new_option_name'); ?>" /></td>
        </tr>
         
        <tr valign="top">
        <th scope="row">Some Other Option</th>
        <td><input type="text" name="some_other_option" value="<?php echo get_option('some_other_option'); ?>" /></td>
        </tr>
        
        <tr valign="top">
        <th scope="row">Options, Etc.</th>
        <td><input type="text" name="option_etc" value="<?php echo get_option('option_etc'); ?>" /></td>
        </tr>
    </table>
    
    <p class="submit">
    <input type="submit" class="button-primary" value="<?php _e('Save Changes') ?>" />
    </p>

</form>
</div>
<?php } ?>

Pitfalls

The Settings name, the second parameter in the register_setting() function, MUST match the name of the option being updated in the database!
For example, say you have add_option( 'foo_bar', 'isfoo' ), you MUST use foo_bar as the second parameter for the register_setting() function. Otherwise WordPress does not know which setting it is suppose to update and it will fail to update.