arrow_back
Back

WordPress admin screens: settings API, list tables, and UI patterns

Andrew Dorokhov Andrew Dorokhov schedule 5 min read
menu_book Table of Contents

WordPress provides two core APIs to make the administrative interfaces easy to build (Settings API and Options API).

The Settings API focuses on providing a way for developers to create forms and manage form data.

It allows to define settings pages, sections within those pages and fields within the sections.

Page -> Sections -> Fields

What you get for free by using the Settings API instead of handling the form yourself:

  • Handling form submissions — WordPress takes care of retrieving and storing your $_POST submissions.
  • Security measures — nonces and capability checks are built in.
  • Sanitizing data — you get access to the same methods that the rest of WordPress uses for ensuring strings are safe to use.

1. Register settings

These functions should all be added to the admin_init action hook.

Setting is a parameter that will be stored in a DB. We used to call it option.

We must define a new setting using register_setting(), it will create an entry in the {$wpdb->prefix}_options table. It has no effect on the displaying fields.

function register_my_setting() {

    register_setting(
        string $option_group,               // A settings group name.
        string $option_name,                // The name of an option to sanitize and save.
        [                                   // array $args = array()
            string $type,                   // The data type for the option value (e.g., 'string', 'integer', 'boolean', etc.).
            string $description,            // A brief description of the setting.
            callable $sanitize_callback,    // A callback function to sanitize and validate the setting's value.
            bool|array $show_in_rest,       // Optional. Whether to expose this setting in the REST API. Can be a boolean or an array.
            mixed $default                  // Optional. The default value for the setting.
        ]
    );
}

add_action( 'admin_init', 'register_my_setting' );

open_in_new Some notes about the elements in the $args parameter .

Settings are typically grouped together, and the option_group parameter helps organize them. It’s used in the settings_fields() function for security measures. It’s used to avoid conflicts between settings with similar names that might belong to different themes or plugins.

2. Creating sections

Section is a key concept. We create a section, then we attach it to some page, and add to this section settings fields.

We can’t show any settings without a section.

add_settings_section( 
    string $id,             // Slug-name to identify the section. Used in the 'id' attribute of tags.
    string $title,          // Formatted title of the section. Shown as the heading for the section.
    callable $callback,     // Function that echos out any content at the top of the section (between heading and fields).
    string $page,           // The slug-name of the settings page on which to show the section.
    array $args = array()
)

$page parameter can be any string. We only use it when we show this section:

do_settings_sections( string $page );

3. Add a field to a section

add_settings_field( 
    string $id,                     // Slug-name to identify the field. Used in the 'id' attribute of tags.
    string $title,                  // Formatted title of the field. Shown as the label for the field during output.
    callable $callback,             // Function that fills the field with the desired form inputs. The function should echo its output.
    string $page,                   // The slug-name of the settings page on which to show the section (general, reading, writing, ...).
    string $section = 'default', 
    array $args = array()
);

We can consider $page and $section combination as a namespace for the fields. Because section ID can be the same within the different pages.

Also, WordPress has magic interaction with the following keys: label_for, class. Settings are displayed in a table. Using label_for we can add label to the field name, and using class we can add a custom CSS class to the tr tag. Moreover, these parameters are accessible in the $callback function. It allows us to add an ID to inputs dynamically.

4. Creating a form on a page

if ( ! current_user_can( 'manage_options' ) ) {
    return;
}

?>
<div class="wrap">
    <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
    <form action="options.php" method="post">
        <?php
        // Outputs nonce, action, and option_page fields for a settings page.
        settings_fields( 'option_group' );
        
        // Outputs setting sections and their fields.
        do_settings_sections( 'my-settings-page' );
        
        // Outputs save settings button.
        submit_button( 'Save Settings' );
        ?>
    </form>
</div>

5. How everything works

The form is sent to the /wp-admin/options.php file.

We can update only options we registered with register_settings().

The option group is sent by the option_page parameter. It’s like a namespace. It means we can update settings only from one option group at once.

Security

Always check the manage_options capability when working with settings:

When using the Settings API, the form POSTs to wp-admin/options.php, which provides fairly strict capabilities checking. Users will need the manage_options capability (and in Multisite will have to be a Super Admin) to submit the form.

Extending the built-in settings pages

The $page argument of add_settings_section() and add_settings_field() accepts the slug of a core settings screen (general, writing, reading, discussion, media, permalinks), which lets us add our own options to a standard page instead of creating a new one.

add_filter( 'admin_init', 'custom_settings_register_fields' );

function custom_settings_register_fields() {
    register_setting( 'reading', 'sort_by_date_old_to_new' );
    add_settings_section( 'sorting_section', 'Sorting Options', '', 'reading' );
    add_settings_field( 'sort_by_date_old_to_new', 'Sort By: Date Old to New', 'custom_settings_fields', 'reading', 'sorting_section' );
}

function custom_settings_fields() {

    $value = get_option( 'sort_by_date_old_to_new', false );

    $on_checked = $off_checked = '';

    if ( $value ) {
        $on_checked = 'checked="checked"';
    } else {
        $off_checked = 'checked="checked"';
    }

    echo '<p>
            <label>
                <input name="sort_by_date_old_to_new" type="radio" value="1" ' . $on_checked . '> On
            </label>
          </p>';

    echo '<p>
            <label>
                <input name="sort_by_date_old_to_new" type="radio" value="0" ' . $off_checked . '> Off
            </label>
          </p>';
}

Additional sources

code

Need Help with Development?

Happy to help — reach out via the contacts or go straight to my Upwork profile.

work View Upwork Profile arrow_forward
Next Article

WordPress code quality checklist: plugins, themes, and reviews

arrow_forward