Using The WordPress Settings API

So I’ve been writing WordPress plugins & widgets for people recently and having to produce administration pages in the dashboard. Using the WP Settings API makes this SO amazingly easy… you barely have to write any code or HTML at all.

Basically it comes down to just this…

* In your constructor you add an action to call a routine to add your admin submenu and add another action to initialize your settings:

if (is_admin()) {
    add_action('admin_menu', array($this, 'add_submenu'));
    add_action('admin_init', array($this, 'options_init'));
}

* Add your add_submenu() function that you referenced above:

public function add_submenu() {
    if (function_exists('add_submenu_page')) {
        add_submenu_page('options-general.php', /* parent slug (hang it off the options menu) */
            'Plugin Admin page', /* page title */
            'My Plugin', /* menu title */
            'edit_posts', /* required user capability */
            'jons-plugin', /* unique menu slug */
            array($this, 'submenu_callback')); /* callback function to generate output */
    }
}

* In the admin_init filter you define what settings are available:

function options_init(){
    // WordPress should enforce this for us because we're a child of the options page
    // But doesn't hurt to be double-checking
    if (current_user_can('edit_posts')) {
        // Use the settings API to do all the heavy lifting for the form
        // register_setting ( option group , option name , sanitize callback )
        register_setting( 'jons-plugin-options-group', 'jons-plugin-options', array($this, 'validate_options'));
 
        // add_setting_section( id , section title , callback function , menu page slug )
        add_settings_section('jons-plugin-section-one', 'First Section Title', array($this, 'display_setting_name'), 'jons-plugin');
        add_settings_section('jons-plugin-section-two', 'Second Section Title', array($this, 'display_setting_number'), 'jons-plugin');
 
        // add_settings_field ( id , field title , callback function , menu page slug , settings section , [arguments] )
        add_settings_field('field-one', 'A Name', array($this, 'plugin_setting_set_name'), 'jons-plugin', 'jons-plugin-section-one');
        add_settings_field('field-two', 'A Number', array($this, 'plugin_setting_set_number'), 'jons-plugin', 'jons-plugin-section-two');
    }
}

Note that we have sections which group together related settings. Each setting is attached to a previously defined section.

* Then we define three groups of functions that options_init() references. First the explanatory text for each section:

function display_setting_name() {
    echo '<p>Enter a name.</p>';
}
 
function display_setting_number() {
    echo '<p>Enter a number.</p>';
}

* And then the callback functions that display the fields for the values. Here we actually have to write a bit of HTML. Notice that we fetch the current value for each field and display it prefilled on the form:

function plugin_setting_set_name($args) {
    $options = get_option('jons-plugin-options');
    echo "<input id='jons-plugin-options[field-one]' name='jons-plugin-options[field-one]' size='40' type='text' value='".$options['field-one']."' />";
}
 
function plugin_setting_set_number($args) {
    $options = get_option('jons-plugin-options');
    echo "<input id='jons-plugin-options[field-two]' name='jons-plugin-options[field-two]' size='4' type='text' value='".$options['field-two']."' />";
}

* Then define the function that validates our user’s input. Note that we DON’T validate in-place in the array that WordPress passes us – we create a new array and we copy the validated input into this array. This prevents anything dodgy happening if fields that we’re not expecting are present in the array – this way we’re guaranteed to only get good valid and expected data in our output array:

function validate_options($input) {
    $valid_input = array();
    $valid_input['field-one'] = substr(sanitize_text_field($input['field-one']), 0, 40);
    $valid_input['field-two'] = intval($input['field-two']);
    return $valid_input;
}

* Remember that call to add_submenu_page() back up at the top? That registered our callback for when the admin menu’s selected. So we better write the code that produces it:

function submenu_callback() {
screen_icon();
echo "<h2>Jons Plugin - Admin Page</h2>";
?>
 
<form method="post" action="options.php">
<?php settings_fields( 'jons-plugin-options-group' ); /* settings_fields( settings group name ) */ ?>
<?php $options = get_option( 'jons-plugin-options' ); /* */ ?>
<?php do_settings_sections('jons-plugin'); /* do_settings_sections( settings page slug name ) */?>
<p class="submit">
<input type="submit" class="button-primary" value="Save Settings" />
</p>
</form>
<?php
}

This is outputting the settings form and auto-generating all the fields based on the options that we’ve defined higher up. And that… believe it or not… is all we have to do! As well as calling our functions to create the HTML for the individual form elements, WordPress also inserts a couple of hidden fields – but more of those another day.

In summary, we’ve
– inserted the menu in the appropriate part of the dashboard
– defined the sections & fields that are on that menu
– defined header text for each section
– defined callback functions to generate the HTML <input /> tags for each field
– defined a function to validate the user’s input
– and created the skeleton of the settings page itself – which passes off most of its work to the settings API

WordPress automatically handles all the saving of our data into the wp-options table and reading it out again for us.

As you can see in the functions where we prefilled the form with the current setting values, the rest of your code can easily access the current values of your settings by reading the option out of the wp-options table and then parsing it as an array of named elements:

    $options = get_option('jons-plugin-options');
    //$options['field-one'];
    //$options['field-two'];

And this produces an admin page that looks like this:

The full file, wrapped up as a class, is available for download here

1 comment to Using The WordPress Settings API