One of the most confusing aspects of working with WordPress is the Settings API.
In an attempt to make a little bit easier to understand, I’ve written a series that takes a long look at the API as well as an example project that’s available for download for others to study (and to contribute to in order to improve).
But, as with most things in programming, there are still things that can crop up now and again that can leave you scratching your head. Case in point: Let’s say that you want to introduce two sections (or three or four, even) to a single options page.
Unless you do this correctly, you’re likely to notice that the ‘Save Changes’ button will only save the changes to the last group of options. Luckily, there’s an easy way to keep your options logically grouped while also maintaing serialization through a single ‘Save Changes’ button.
Multiple Sections on WordPress Options Pages
Before going forward, there are a couple of things that are worth nothing:
- The code here is purely for example purposes.
- There are a number of best practices that I’m not following (such as separating out my markup, giving my input options semantic names, and I’m not doing any sanitization).
Obviously, the point is to share poor examples of how to do something, but to show a quick example of how to add multiple settings to a page. Since I – and many others – have covered separation of concerns, semantics, and sanitization elsewhere – there’s no need to reinvent the wheel.
First, we’re going to be created a page that looks like this (assuming that you’re running the latest version of WordPress which happens to be 3.9 at the time of this writing):
In order to get this particular screen to display, we need to use several functions:
- add_options_page
- add_settings_section
- add_settings_field
- register_setting
- do_settings_sections
- settings_fields
- submit_button
If you’re familiar with either the Settings API or the Options API, then you’re likely familiar with all of these functions, at least on some level.
But before looking at the correct solution for how to add multiple sections on a WordPress options pages, let’s look at an example of what not to do (because this tends to be the most common things that I’ve seen and that I’ve committed myself).
The Usual First Step
The first thing that’s normally done when setting up options pages is defining the actual option page, menu item, and so on. In order to do this, we make a call to add_options_page
and hook it to the admin_menu
action.
Check out the following gist for more information:
Note that this gist is not complete as it doesn’t provide the function used to render the page. I’ll cover that a little bit later in this article because this is where things usually get confusing.
So before looking at that, let’s see how to define the first section and option that appears on the options page. Specifically, it’s nothing for than a text box that accepts a value and displays it after it’s been saved.
At this point, let’s aim to define a new section along with another option. Again, I’m using a single input field for the purposes of demonstrating the point.
Now, all that’s left to do is to define a function for rendering the settings, the fields, and the markup for displaying the form, the title, and the submit button.
But this is where we go wrong.
What Is the Problem?
In the most recent gist displayed above, you’ll notice that we’re making a single call to do_settings_section
and two calls to settings_fields
.
Based on the function names, it appears as if we’re instruction WordPress to do something with a certain section and then to render the two fields that we’ve defined, and although that’s somewhat true, it’s still a bit misleading.
Instead, the do_settings_section
requires that we pass it the ID of the page on which the options will be displayed – not the name of the section that we’ve created. So in our case, this means that we need to specify acme-options-page
.
Secondly, the settings_fields
function requires that we pass the ID of the group options that we’ve defined. So rather than passing what we have above, we need to pass acme-settings
.
But this requires another change in our code.
And How Do We Fix It?
In order to make sure that the settings_fields
function renders the proper information, we need to update the register_setting
call of our code so that it’s associating our sections and fields with the same setting.
For example, we need to change it from acme-settings-one
and acme-settings-two
to acme-settings
.
In short, the do_settings_section
isn’t looking for the unique sections that we’ve created – it’s looking for the entire page. Secondly, the settings_fields
function isn’t looking for each field that we’ve created, it’s looking for the group that we’ve created when defining register_setting
. To that end, the key to all of this is to make sure that when we call register_setting
for each of our fields, we’re giving them the same identifier.
This is what will allow us to make sure that we can have multiple sections on WordPress options pages while still being able to save and read them properly.
This will result in the follow, complete working set of code:
Test It Out Yourself
Given the gist above, you should be able to copy and paste the code into the functions.php
file of, say, twentyfourteen and see a new menu item along with an options page.
Remember, this is just code meant to demonstrate an example and does not fully follow conventions that I recommend using in production code – the primary point of all of the above is to give an example of how to display multiple sections on an options page. Nothing more.