6.2. WordPress Settings API

In the previous blog, we add a sub menu to admin menu to accept common settings from users. In this blog, we add sections and fields to the menu page.

WordPress Settings API allows developers to add form pages to Admin screen by defining pages, sections and fields and partially automates the form and data management.

But before that, we briefly touch upon WordPress Options API, which we use to store plugins’ settings or options in WordPress database.

WordPress Options

WordPress Settings API - Share on Social options

WordPress Options API is an easy way to store plugins data in WordPress database. With WordPress Options we can add, delete, update data which is stored in wp_options table as key and value pairs. Some of the frequently used functions to manage WordPress Options are

In Share on Social Plugin, we use an assoc array to hold Facebook App ID, Google Client ID and Debug boolean flag. This array is saved as as WordPress Options under option name sos_common_options.

share-on-social/admin/class-options.php

class Sos_Options {

    public function setup () {

        .... 

        add_action( 'admin_init',array($this,'init_common_options') );

    }

    public function init_common_options () {

        $option_group = 'sos_common_options';

        // no options - create them.
        if ( false == get_option( $option_group ) ) {
            add_option( $option_group );
        }
                
        $options = get_option( $option_group );

        if ( false == isset( $options<a href="http://codex.wordpress.org/Function_Reference/add_settings_section" target="_blank">'fbappid']) ) ) {
            $options['fbappid']) = '';
        }

        ...
    }

In setup() we add init_common_options() method as action to admin_init hook. WordPress executes this method when it reaches admin_init stage.

In init_common_options() method, we check whether option sos_common_options already exists in database using get_option() function. If it doesn’t exists, then we add an empty option using add_option() method. If exists, then we get the option value and assign it $options. Next, we check whether $options[‘fbappid’] is set and if not set then set it to an empty string. We do similarly for Google Client ID and Debug flag. At this stage, $options array is primed either with empty strings or if option exists, then the values read from the database.

Before we can display the options in a form, we have to register them with WordPress as fields using WordPress Settings API.

 
 

WordPress Settings API

To register or add fields, use WordPress Settings API functions - add_settings_section() and add_settings_field()..

The following snippet shows how FB App ID field is added as settings.

share-on-social/admin/class-options.php

    public function init_common_options () {

        $option_group = 'sos_common_options';
        $section = 'sos_common_options_section';

        // no options - create them.
        if ( false == get_option( $option_group ) ) {
            add_option( $option_group );
        }
                
        $options = get_option( $option_group );

        if ( false == isset( $options<a href="http://codex.wordpress.org/Function_Reference/register_setting" target="_blank">'fbappid']) ) ) {
            $options['fbappid']) = '';
        }
        
        add_settings_section( $section, '', '', $option_group );
        
        $label = __( 'Facebook App ID', 'sos-domain' );        
        add_settings_field( 'fbappid', $label, array($this,'textinput'), $option_group, $section, 
                            array('id' => 'fbappid',
                                  'name' => 'sos_common_options[fbappid]',
                                  'value' => $options['fbappid']) );

        // similarly register other fields of the page

        // finally
        register_setting( $option_group, $option_group,array($this,'sanitize_options') );
    }

Section is just grouping of fields. We name section as sos_common_options_section and add a page sos_common_options to it. To the page, we add FB App ID field using add_settings_field() which takes following arguments.

  • id - we use fbappid as the id of the field.

  • title - field label.

  • callback function - for the field, we need a text input field to accept the app id from the user and we pass textinput() method as the callback function which renders the text input field.

  • page - to which this field belongs.

  • section - to which this field belongs. this is optional.

  • args - use this to pass arguments to callback function.

This function just adds or registers field with WordPress and it doesn’t render. Instead, for the each field a callback function and arguments to callback are specified. In the above code, we have attached textinput() method as callback with argument array('id' => 'fbappid', 'name' => 'sos_common_options[fbappid]', 'value' => $options['fbappid']). Actual rendering happens much later when user clicks the menu item, WordPress calls the textinput() method with the said argument which renders the text input field for FB App ID.

share-on-social/admin/class-options.php

    function textinput ( $args, $echo = true ) {
        $html = '<input class="text" type="text" id="' . $args[ 'id' ] .
                 '" name="' . $args[ 'name' ] . '" size="30" value="' .
                 $args[ 'value' ] . '"/>';
        if ( $echo ) {
            echo $html;
        } else {
            return $html;
        }
    }

Method textinput()is just a helper method that echo the HTML input element. Parameter $args holds the array passed by add_settings_field() and it used as attributes to input element which are

  • id - we use fbappid as id.

  • name - string ‘sos_common_options[fbappid]’ tells WordPress Settings API that on form submit, value of this element should be saved in option named sos_common_options and at assoc index ‘fbappid’ .

  • value - $options[‘fbappid’] is set as value of text input field.

Similarly, we add other fields Google Client ID and Debug flag. For the last one, we use checkbox() method as callback to display the HTML checkbox.

Finally, we register one more callback function with register_setting() which is used to register sanitize_options() method as callback. When user submit the page, WordPress uses the callback to sanitize the values entered by the user.

share-on-social/admin/class-options.php

    function sanitize_options ( $input ) {

        $output = array();
        foreach ( $input as $key => $val ) {
            if ( isset( $input<a href="http://codex.wordpress.org/Function_Reference/wp_filter_nohtml_kses" target="_blank"> $key ] ) ) {
                $output[ $key ] = wp_filter_nohtml_kses( $input[ $key ] );
            }
        }
        return apply_filters( 'sanitize_options', $output, $input );

    }

When options are about to be saved to database, WordPress calls this method with options as array of key and value pairs. We use WordPress function wp_filter_nohtml_kses() to strip scripts or tags in input value so that they don’t get into database.

Lot of things going on here. Let’s recap what we have done so far.

  1. add a sub menu and registered a page for that menu item.

  2. tell WP to add some fields to the page.

  3. tell WP which method to call to render each field and what args to pass on to rendering methods.

  4. tell WP which method to sanitize the option when saving to database.

At this point, WordPress knows about the fields to display and how to render them. It also knows how to sanitize and save them. But it doesn’t know how to render the page.

Last thing we have to do to complete this menu item is tell WP how to render the page. In the next section, we show how to render page with WordPress Settings API.