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
$_POSTsubmissions. - 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_initaction 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 themanage_optionscapability (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>';
}
Andrew Dorokhov