Adding Multiple Sections on WordPress Options Pages

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):

WordPress Options Page

In order to get this particular screen to display, we need to use several functions:

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.

10 Comments

I found the Settings API VERY confusing and clunky when I use it. One of the motivations behind the Pico Plugin Framework was an attempt to make using the Settings API a bit easier.

(That reminds me, I should really write some tutorials on using it ;-)

    Yeah – that Settings API is not intuitive. It does a lot of neat things and handles a lot of manual labor, so to speak, but it comes at the expense of needing to understand how all of the pieces fit together.

    This is why I tend to share my notes in posts like this — it’s so that it hopefully helps others out, but also something for me to refer back to in future work ;).

I think there is a typo on the last block of code, line 78: “acme-input-field-one” should be “acme-input-field-two”, right?

I hope this kind of skeleton gets added to the WordPress Plugin Boilerplate, so we stop creating those setting pages on a non-standard way :-)

    I think there is a typo on the last block of code, line 78: “acme-input-field-one” should be “acme-input-field-two”, right?

    All fixed — thanks! :)

    I hope this kind of skeleton gets added to the WordPress Plugin Boilerplate, so we stop creating those setting pages on a non-standard way :-)

    Funny that you mention this! The direction that we’re taking this, the Boilerplate won’t include this natively; however, we’re planning to have a number of extensions or use cases (or whatever you want to call them) for how to leverage the Boilerplate for certain tasks such as this (as well as doing things such as meta boxes, etc).

Oh boy… The Settings API.
I’ve done several plugin and theme’s options pages using it with no joy when I need to come back to update something in them.. On my next project I’ll have a look to the Redux Framework.

    I’ve done several plugin and theme’s options pages using it with no joy when I need to come back to update something in them..

    Gotta document that stuff, otherwise you’re left scratching your head, right? :)

    I’ve been hearing more and more about the Redux Framework lately. I’m personally hesitant to use frameworks that sit on top of the Settings API (for my own reasons), but if it stays updates and helps others get stuff done quicker, then by all means!

Hi Tom,
After following many of your posts and TutsPlus and right here, I’ve noticed that you seem to use the Settings API in a ‘vanilla’ state without resorting to loops and such to automate the tasks that you could. Also I know that you’re not keen on using wrappers over the top of the API. My question is, in a ‘real world’ theme or application would you set up your options settings in the way you describe in your tutorials or would you create other functions that carry out some of the heavy-lifting?

    My question is, in a ‘real world’ theme or application would you set up your options settings in the way you describe in your tutorials or would you create other functions that carry out some of the heavy-lifting?

    It really depends, but usually no and it’s because of this: Experience has shown me that if I try to abstract or automatic too much of the process, then I end up accidentally accruing technical debt that requires me to go back and un-refactor, if you will, the code I tried to make mroe efficient by adding loops and other common procedures to write less code.

    There’s more I could write about this, but that’s the very short gist of it.

      Thanks for the reply Tom. Yes I agree, I’ve made a few attempts at classes that automate some of the work but they often end up as long and more complex than using the functions in the normal way. Keep up the great work in demystifying WordPress’ many APIs!

Leave a Reply

Name and email address are required. Your email address will not be published.

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>