When it comes to developing WordPress Themes and Plugins, there are a number of different ways developers are creating their menus, options, and validation functionality. The thing is, there's really only one way to properly do this within WordPress: the Settings API.
This series is aiming to be the definitive guide for how to take advantage of the WordPress Settings API so that you have a single point of reference for properly developing your themes and plugins.
In the first article in this series we took a broad look at the Settings API and why it matters. Here, we're going to begin diving into the API and how to take advantage of everything that it offers.
We'll take a look at the foundational units of WordPress options - sections, fields, and settings - and how to include them in the native WordPress Dashboard.
On Sections, Fields, and Settings
Before we get into writing any code, it's important to understand the three main components of the WordPress Settings API.
- Fields are individual options that appear on menu pages. Fields correspond to actual elements on the screen. That is, a field is managed by a text box, radio button, checkbox, etc. Fields represent a value stored in the WordPress database.
- Sections are a logical grouping of fields. Whenever you're working with multiple fields, you're likely going to be grouping related options together - Sections represent this grouping. Furthermore, if your work includes multiple administration pages, each section often corresponds to its own menu page (though you can also add them to existing sections).
- Settings are registered after you've defined both Fields and Sections. Think of Settings as a combination of the Field and the Section to which it belongs.
At this point, don't worry if you're still unclear about any of the major components. We're going to take an in-depth look at each component along with example source code that ties it all together.
A Sandbox for Our Settings
In order to get started programming against the Settings API, let's setup a basic theme that can be used throughout this article and the rest of the series. All of the source code is available on GitHub, too.
In your local installation of WordPress, navigate to the "themes" directory and create a new, empty directory and call it "WordPress-Settings-Sandbox." Add the following three files:
- style.css – This is the stylesheet for the theme. It includes all meta information for the theme. It's required by WordPress
- index.php – This is the default template for the theme. It can be empty at first. It's required by WordPress
- functions.php – This is where we'll be doing most of our work. We'll be filling this out throughout the tutorial
Add the following code to style.css:
/* Theme Name: WordPress Settings Sandbox Theme URI: YOUR URI Description: A simple theme used to showcase the WordPress Settings API. Author: YOUR NAME Author URI: YOUR WEBSITE Version: 0.1 License: Copyright 2012 YOUR NAME (YOUR EMAIL ADDRESS) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
Next, add the following code to index.php:
<!DOCTYPE html> <html> <head> <title>The Complete Guide To The Settings API | Sandbox Theme</title> </head> <body> <div id="header"> <h1>Sandbox Header</h1> </div><!-- /#header --> <div id="content"> <p>This is theme content.</p> </div><!-- /#content --> <div id="footer"> <p>© <?php echo date('Y'); ?> All Rights Reserved.</p> </div><!-- /#footer --> </body> </html>
Note that the above markup is extraordinarily simple and I do not recommend using this as a foundation for theme development. It's tailored for this series of articles and is simply providing the means by which we will be reading values from the Settings API.
In the Themes administration screen, refresh the page and you should see the new Sandbox theme appear. Go ahead and activate it.
At this point, we're ready to get started.
Our First Set of Options
Notice in the index template above, we've defined three specific content regions: header, content, and footer. Using the Settings API, let's create a "General" section containing three fields, each of which corresponds to one of the specific content regions we've just defined.
Before writing any code, I always find it helpful to list out exactly what I need to do. In this case, we need to do the following:
- Define a section that will be used to group each field
- Add three fields - one for each content region - to the section defined above
- Register the settings with the WordPress API.
In order to avoid any massive blocks of code and to make sure that we're covering all of our bases, we'll be taking each of the above items point by point.
Creating the Section
In order to find our "General" section of options, we're going to need to use the add_settings_section function of the Settings API. According to the WordPress Codex, add_settings_section requires three arguments:
- ID – This is the unique identifier for this particular section. Note that this is the value that will be used to register each field within this section. Feel free to name it whatever you want, but I recommend making it clear for the sake of readability.
- Title – This value will be displayed at the top of the page in the WordPress Dashboard when users are working with your options.
- Callback – This is the name of a function that we'll define that will render text on the screen for the function. It can be used for a variety of functionality. In the simplest case, it can be used to provide a set of instructions or description for your option page.
- Page – This value is used to tell WordPress on which page your options should be displayed. In a future article, we'll use this to add options to our own custom pages. For now, we'll be adding this to the existing General Options page.
With that, let's go ahead and define our section. Take a look at the following, commented code. We're adding this to our functions.php file.
A word about the code snippets in this series: don't simply copy and paste this code. Take time to read each line, see how the arguments correspond with each API function that we cover, and follow the corresponding comments to make sure you get the hang of what we're doing:
<?php /* ------------------------------------------------------------------------ * * Setting Registration * ------------------------------------------------------------------------ */ /** * Initializes the theme options page by registering the Sections, * Fields, and Settings. * * This function is registered with the 'admin_init' hook. */ add_action('admin_init', 'sandbox_initialize_theme_options'); function sandbox_initialize_theme_options() { // First, we register a section. This is necessary since all future options must belong to one. add_settings_section( 'general_settings_section', // ID used to identify this section and with which to register options 'Sandbox Options', // Title to be displayed on the administration page 'sandbox_general_options_callback', // Callback used to render the description of the section 'general' // Page on which to add this section of options ); } // end sandbox_initialize_theme_options /* ------------------------------------------------------------------------ * * Section Callbacks * ------------------------------------------------------------------------ */ /** * This function provides a simple description for the General Options page. * * It is called from the 'sandbox_initialize_theme_options' function by being passed as a parameter * in the add_settings_section function. */ function sandbox_general_options_callback() { echo '<p>Select which areas of content you wish to display.</p>'; } // end sandbox_general_options_callback ?>
Make sense? Generally speaking, it doesn't look like much but navigate to your Settings menu and click on General. Scroll to the bottom of the page and you should see your new section of options.
You can add this section to any of the pages under the Settings menu. In the above example, we've passed "general" as the last parameter to the add_settings_section, but if you'd like to add it to a different page, you can provide a different page title. Here's a reference for each of the Settings pages and their corresponding key:
- General, "general"
- Writing, "writing"
- Reading, "reading"
- Discussion, "discussion"
- Media, "media"
- Privacy, "privacy"
- Permalinks, "permalink"
Adding Fields
Now that we have a section defined, we can introduce a few options. Recall that in our index template we defined three specific container elements: header, content, and footer.
Though we'll be introducing more options throughout the course of this series, today we're going to introduce a way to toggle the visibility of each of the above elements.
Similar to what we did with the settings section, I like to list out exactly what we need to do before writing any code. Since we're going to be toggling each of the content areas...
- We're going to need three options - one for each area of content
- Since we're toggling visibility, we can use a checkbox as our interface element
At this point, we're ready to introduce the first settings field. To do this, we'll use the add_settings_field function. This function takes six parameters (four required, two optional). They are as follows:
- ID – The ID of the actual field. This will be used to save and retrieve the value throughout the theme. I recommend naming this something meaningful for improving readability of your code.
- Title – This value applies a title to the field option on the administration page. This should be clear as it will be read by end users.
- Callback – This is the name of the function that is used to render the actual interface element with which users will interact.
- Page – Similar to the section we outlined, this parameter identifies on which page this option should reside. If you're only introducing a single option, you can add it to an existing page rather than a section that you've defined.
- Section – This refers to the section that you've created using the add_settings_section function. This value is the ID that you specified when creating your section. This is an optional parameter.
- Arguments – This is an array of arguments that are passed to the callback function. This is useful if there is additional information that you want to include in rendering your option element. This is an optional parameter.
With that said, let's go ahead and define our first setting field. Specifically, we'll be introducing an option to toggle the visibility of the header.
First, we make a call to add_settings_field just below the add_settings_section function call in the initialization function we wrote in the first part of the tutorial. Review each line and the comments for each option:
// Next, we will introduce the fields for toggling the visibility of content elements. add_settings_field( 'show_header', // ID used to identify the field throughout the theme 'Header', // The label to the left of the option interface element 'sandbox_toggle_header_callback', // The name of the function responsible for rendering the option interface 'general', // The page on which this option will be displayed 'general_settings_section', // The name of the section to which this field belongs array( // The array of arguments to pass to the callback. In this case, just a description. 'Activate this setting to display the header.' ) );
Next, we define the callback referred to in the above function. This callback is used to render the checkbox and the description on the administration page:
/** * This function renders the interface elements for toggling the visibility of the header element. * * It accepts an array of arguments and expects the first element in the array to be the description * to be displayed next to the checkbox. */ function sandbox_toggle_header_callback($args) { // Note the ID and the name attribute of the element should match that of the ID in the call to add_settings_field $html = '<input type="checkbox" id="show_header" name="show_header" value="1" ' . checked(1, get_option('show_header'), false) . '/>'; // Here, we will take the first argument of the array and add it to a label next to the checkbox $html .= '<label for="show_header"> ' . $args[0] . '</label>'; echo $html; } // end sandbox_toggle_header_callback
As far as the checkbox is concerned, pay attention to the comments, but don't worry too much about some of the attributes that you don't recognize (such as a call to the checked() function). Later in this series, we're going to take a look at each input element and their corresponding helper functions.
By now, your functions.php file should look like this:
<?php /* ------------------------------------------------------------------------ * * Setting Registration * ------------------------------------------------------------------------ */ /** * Initializes the theme options page by registering the Sections, * Fields, and Settings. * * This function is registered with the 'admin_init' hook. */ add_action('admin_init', 'sandbox_initialize_theme_options'); function sandbox_initialize_theme_options() { // First, we register a section. This is necessary since all future options must belong to one. add_settings_section( 'general_settings_section', // ID used to identify this section and with which to register options 'Sandbox Options', // Title to be displayed on the administration page 'sandbox_general_options_callback', // Callback used to render the description of the section 'general' // Page on which to add this section of options ); // Next, we will introduce the fields for toggling the visibility of content elements. add_settings_field( 'show_header', // ID used to identify the field throughout the theme 'Header', // The label to the left of the option interface element 'sandbox_toggle_header_callback', // The name of the function responsible for rendering the option interface 'general', // The page on which this option will be displayed 'general_settings_section', // The name of the section to which this field belongs array( // The array of arguments to pass to the callback. In this case, just a description. 'Activate this setting to display the header.' ) ); } // end sandbox_initialize_theme_options /* ------------------------------------------------------------------------ * * Section Callbacks * ------------------------------------------------------------------------ */ /** * This function provides a simple description for the General Options page. * * It is called from the 'sandbox_initialize_theme_options' function by being passed as a parameter * in the add_settings_section function. */ function sandbox_general_options_callback() { echo '<p>Select which areas of content you wish to display.</p>'; } // end sandbox_general_options_callback /* ------------------------------------------------------------------------ * * Field Callbacks * ------------------------------------------------------------------------ */ /** * This function renders the interface elements for toggling the visibility of the header element. * * It accepts an array of arguments and expects the first element in the array to be the description * to be displayed next to the checkbox. */ function sandbox_toggle_header_callback($args) { // Note the ID and the name attribute of the element match that of the ID in the call to add_settings_field $html = '<input type="checkbox" id="show_header" name="show_header" value="1" ' . checked(1, get_option('show_header'), false) . '/>'; // Here, we will take the first argument of the array and add it to a label next to the checkbox $html .= '<label for="show_header"> ' . $args[0] . '</label>'; echo $html; } // end sandbox_toggle_header_callback ?>
At this point, refresh the General Settings page. You should see your checkbox with the "Header" label and a description beside the checkbox.
Unfortunately, it's not actually saving the value to the database yet.
Registering Our Settings
In order to get our fields to actually save to the database, we need to register them with WordPress. Doing this is relatively easy - we just need to take advantage of the register_setting function.
This function accepts three arguments (two required, one optional):
- Option Group – This is actually the name of the group of options. This can either be an existing group of options provided by WordPress or an ID that we specified when creating our own settings section. This argument is required.
- Option Name – This is the ID of the field that we're registering. In our case, we're only registering a single field, but if we were registering multiple fields, then we'd need to call this function for each field we're registering. We'll see more on this in a moment. This argument is required.
- Callback – This argument requires the name of a function that will be called prior to saving the data to the database. This argument is outside the scope of this article but we'll be visiting it before the series is over. This argument is optional.
At this point, let's register the setting that we've just created. Take a look at the code below. Add this line of code directly below the call to add_settings_field in the initialize function we defined earlier in the article. It's arguably the easiest to follow out of all of the snippets in this article:
// Finally, we register the fields with WordPress register_setting( 'general', 'show_header' );
Try it out - check the checkbox, click on 'Save Changes,' and notice that when the page refreshes, the option has changed. Uncheck the checkbox, save, and watch it save.
Easy enough, right?
Adding the Final Two Options
We still need to introduce the options for toggling the visibility of the content area and the footer area. It's almost exactly the same as how we setup the option for toggling the header.
First, let's define the field for displaying the content area. This will go under the first call to add_settings_field:
add_settings_field( 'show_content', 'Content', 'sandbox_toggle_content_callback', 'general', 'general_settings_section', array( 'Activate this setting to display the content.' ) );
And let's setup the callback function:
function sandbox_toggle_content_callback($args) { $html = '<input type="checkbox" id="show_content" name="show_content" value="1" ' . checked(1, get_option('show_content'), false) . '/>'; $html .= '<label for="show_content"> ' . $args[0] . '</label>'; echo $html; } // end sandbox_toggle_content_callback
Next, let's define the field for displaying the footer area:
add_settings_field( 'show_footer', 'Footer', 'sandbox_toggle_footer_callback', 'general', 'general_settings_section', array( 'Activate this setting to display the footer.' ) );
And setup the callback for this field, too:
function sandbox_toggle_footer_callback($args) { $html = '<input type="checkbox" id="show_footer" name="show_footer" value="1" ' . checked(1, get_option('show_footer'), false) . '/>'; $html .= '<label for="show_footer"> ' . $args[0] . '</label>'; echo $html; } // end sandbox_toggle_footer_callback
Finally, let's register these two new fields with WordPress. These two function calls go at the bottom of the initialize function we defined earlier in the article.
register_setting( 'general', 'show_content' ); register_setting( 'general', 'show_footer' );
The final version of functions.php should look like this:
<?php /* ------------------------------------------------------------------------ * * Setting Registration * ------------------------------------------------------------------------ */ /** * Initializes the theme options page by registering the Sections, * Fields, and Settings. * * This function is registered with the 'admin_init' hook. */ add_action('admin_init', 'sandbox_initialize_theme_options'); function sandbox_initialize_theme_options() { // First, we register a section. This is necessary since all future options must belong to one. add_settings_section( 'general_settings_section', // ID used to identify this section and with which to register options 'Sandbox Options', // Title to be displayed on the administration page 'sandbox_general_options_callback', // Callback used to render the description of the section 'general' // Page on which to add this section of options ); // Next, we will introduce the fields for toggling the visibility of content elements. add_settings_field( 'show_header', // ID used to identify the field throughout the theme 'Header', // The label to the left of the option interface element 'sandbox_toggle_header_callback', // The name of the function responsible for rendering the option interface 'general', // The page on which this option will be displayed 'general_settings_section', // The name of the section to which this field belongs array( // The array of arguments to pass to the callback. In this case, just a description. 'Activate this setting to display the header.' ) ); add_settings_field( 'show_content', 'Content', 'sandbox_toggle_content_callback', 'general', 'general_settings_section', array( 'Activate this setting to display the content.' ) ); add_settings_field( 'show_footer', 'Footer', 'sandbox_toggle_footer_callback', 'general', 'general_settings_section', array( 'Activate this setting to display the footer.' ) ); // Finally, we register the fields with WordPress register_setting( 'general', 'show_header' ); register_setting( 'general', 'show_content' ); register_setting( 'general', 'show_footer' ); } // end sandbox_initialize_theme_options /* ------------------------------------------------------------------------ * * Section Callbacks * ------------------------------------------------------------------------ */ /** * This function provides a simple description for the General Options page. * * It is called from the 'sandbox_initialize_theme_options' function by being passed as a parameter * in the add_settings_section function. */ function sandbox_general_options_callback() { echo '<p>Select which areas of content you wish to display.</p>'; } // end sandbox_general_options_callback /* ------------------------------------------------------------------------ * * Field Callbacks * ------------------------------------------------------------------------ */ /** * This function renders the interface elements for toggling the visibility of the header element. * * It accepts an array of arguments and expects the first element in the array to be the description * to be displayed next to the checkbox. */ function sandbox_toggle_header_callback($args) { // Note the ID and the name attribute of the element match that of the ID in the call to add_settings_field $html = '<input type="checkbox" id="show_header" name="show_header" value="1" ' . checked(1, get_option('show_header'), false) . '/>'; // Here, we will take the first argument of the array and add it to a label next to the checkbox $html .= '<label for="show_header"> ' . $args[0] . '</label>'; echo $html; } // end sandbox_toggle_header_callback function sandbox_toggle_content_callback($args) { $html = '<input type="checkbox" id="show_content" name="show_content" value="1" ' . checked(1, get_option('show_content'), false) . '/>'; $html .= '<label for="show_content"> ' . $args[0] . '</label>'; echo $html; } // end sandbox_toggle_content_callback function sandbox_toggle_footer_callback($args) { $html = '<input type="checkbox" id="show_footer" name="show_footer" value="1" ' . checked(1, get_option('show_footer'), false) . '/>'; $html .= '<label for="show_footer"> ' . $args[0] . '</label>'; echo $html; } // end sandbox_toggle_footer_callback ?>
Now refresh the General Settings page and notice you have all three fully functional checkboxes.
Reading the API
What good are options if we can't take advantage of them throughout our theme or our plugin? We need to be able to read the values in order to properly manage our new options.
To do this, we need to use the get_option function. This function accepts two arguments (one required, one optional):
- Option ID – This argument is the ID of the field for the value you're attempting to retrieve. This argument is required.
- Default Option – This is the value the function will return if the function returns an empty value (such as in the case that the option is not found in the database). This argument is optional.
First, let's try to toggle the visibility of the header. In the index template that we created earlier in this article, locate the element with the ID of header. It should look like this:
<div id="header"> <h1>Sandbox Header</h1> </div><!-- /#header -->
Next, let's make a call to get_option in the context of a conditional. If the conditional evaluates to true (that is, the option has been checked on the General Settings page), then the element will be displayed; otherwise, the element will not display.
<?php if(get_option('show_header')) { ?> <div id="header"> <h1>Sandbox Header</h1> </div><!-- /#header --> <?php } // end if ?>
After that, hope over to the General Settings page, check the option for hiding the header element, and refresh your homepage. The header element should no longer appear.
At this point, it's a simple matter of repeating the process for the content and footer element, too. We need to wrap the content and footer elements with conditionals that evaluate the result of get_option calls.
Take a look:
<?php if(get_option('show_content')) { ?> <div id="content"> <p>This is theme content.</p> </div><!-- /#content --> <?php } // end if ?> <?php if(get_option('show_footer')) { ?> <div id="footer"> <p>© <?php echo date('Y'); ?> All Rights Reserved.</p> </div><!-- /#footer --> <?php } // end if ?>
Revisit the General Settings page, toggle each checkbox, and refresh the theme page. Your elements should each toggle independently of one another.
Next Up, Menu Pages
That's it, for now! We've taken a look at all of the functions required for introducing new sections, fields, and settings into WordPress. Of course, there's much more to cover.
In the next article, we'll take a look at how to add custom menu items to the WordPress menu, and how we can introduce our own pages to the WordPress Dashboard.
Related Resources
We covered a lot of material in this article. Here's a reference for everything that we used throughout this article.
Comments