The settings system that I built for Easy Digital Downloads is something I was very happy with once finished, especially because it is very extensible, and very easy to integrate with by other developers. I decided to record an overview video that walks through how the system works.
One of the primary reasons I like the system I built is because of how simple it is for add-on developers to register their own settings within EDD’s main settings tabs. Let’s take a look at the entire code that adds the settings for the Stripe Payment Gateway:
// adds the settings to the Payment Gateways section function edds_add_settings($settings) { $stripe_settings = array( array( 'id' => 'stripe_settings', 'name' => '<strong>' . __('Stripe Settings', 'edds') . '</strong>', 'desc' => __('Configure the Stripe settings', 'edds'), 'type' => 'header' ), array( 'id' => 'live_secret_key', 'name' => __('Live Secret Key', 'edds'), 'desc' => __('Enter your live secret key, found in your Stripe Account Settins', 'edds'), 'type' => 'text', 'size' => 'regular' ), array( 'id' => 'live_publishable_key', 'name' => __('Live Publishable Key', 'edds'), 'desc' => __('Enter your live publishable key, found in your Stripe Account Settins', 'edds'), 'type' => 'text', 'size' => 'regular' ), array( 'id' => 'test_secret_key', 'name' => __('Test Secret Key', 'edds'), 'desc' => __('Enter your test secret key, found in your Stripe Account Settins', 'edds'), 'type' => 'text', 'size' => 'regular' ), array( 'id' => 'test_publishable_key', 'name' => __('Test Publishable Key', 'edds'), 'desc' => __('Enter your test publishable key, found in your Stripe Account Settins', 'edds'), 'type' => 'text', 'size' => 'regular' ) ); return array_merge($settings, $stripe_settings); } add_filter('edd_settings_gateways', 'edds_add_settings'); |
If you have ever setup settings pages for your own WordPress plugins, then you will immediately see how much simpler the above code is than creating an entire page with options.
One of the major benefits of the EDD settings system is that it is highly extensible.
Hi, this is a really nice way to register new settings, you did something very cool!
Thanks Remi!
Awesome tutorial Pippin. I think I’ll go through one of my plugins and re-work that area. Love that you used all the built-in styles; was thinking half-way through this — damn, that’s a lot of copying and pasting I’ll have to do from EDD π
Thanks again!
I really prefer to always use core UI elements, for a few of reasons:
1. It makes the settings integrate flawlessly with WP
2. It dramatically reduces the amount of code you have to maintain
3. It dramatically reduces the likelihood of conflicts with other plugins/themes CSS
Completely agree. I think I was sorta on the right track with what I was doing in my plugins (as far as registering the settings in a big ‘ol array) — but using the settings API — does that take care of sanitation/validation whereas the way I did it wasn’t? Thanks!
You still have to do validation yourself with the settings API, unfortunately.
Bah okay – is that also in EDD in-case I wanted to sneak a peak at how you did it? It looks like about half-way down WPTuts covers it a bit as you mentioned http://wp.tutsplus.com/tutorials/the-complete-guide-to-the-wordpress-settings-api-part-7-validation-sanitisation-and-input-i/
EDD has some basic sanitation at the moment, though I need to enhance it. It is handled by EDD, not by the add-on(s).
Sounds good, thanks for letting me know
Have any suggestions for creating a static tab? For example, if I wanted to have a ‘Documentation’ tab with free text. Thanks!
Think I figured this one out — I just created an output function for the ‘Documentation’ tab and appended that onto the logic for the others — seems to work great!
Yep, that’s what you need π
Few days back I wrote a similar PHP class. Check it out http://tareq.wedevs.com/2012/06/wordpress-settings-api-php-class/
That’s great! The one thing I would suggest on it is that you remove the post box styling from around the settings sections/fields, that way it looks exactly like it is meant to look in WordPress π
Seems like a few of us had the same idea…
I’m updating my plugin to use the Settings API and decided to make a wrapper class. I did take it a little further though. The wrapper class works using filters to register sections and settings using the Settings API. It also extends the Settings API to allow registering of tabs [optional] and the settings sections linked to the tabs It also allows me to set the position of the tab within the tab bank. Same for the settings sections.
I also added filters to allow easy hooking into the class so I can easily add tabs/sections and position them right where where I want.
I did opt to use three arrays for the configuration though. One for tabs, one for sections and the other for the settings all linked by and id. One large array for all three became to mind numbing to look at for me.
So with that said it only takes one command passing two values, the page hook and the current tab [optional], to create the entire settings page.
I’m not done yet though. Right now it just outputs everything to the screen I have no code done to actually save and update settings. But it’s coming along nicely.
Having this will make it insanely easy to create add-ons for my plugin that can hook into its settings page.
It sounds like a lot but it really didn’t take a whole lot of code, a few dozen lines. And since the entire back end of the class is powered by the Settings API it should be forwards compatible and make my plugin code lighter and easier to maintain.
That’s fantastic! Do you plan to release the code, either free or paid?
Well it’ll be bundle with my plugin … I didn’t give it any thought until you mentioned it, but I could throw it up on GitHub.
I did run across a couple small road blocks. It seems the WP Settings API actually isn’t all the robust, I’m learning. Unless I’m mistaken, you can only register one settings section per page/tab so I think I’m going to have slightly re-think on how sections are ID’d because I want to be able to register multiple sections per page/tab and be able to hook into them to add additional sections if I want. Additionally, I’m working on adding set default, reset and remove methods. Seems to me the Settings API should have those, but doesn’t. At least the update_options function can be used so that should ensure forward compatibility.
While I’m rambling …. I’m thinking of adding the option of registering contextual help screens too for settings pages. That way one could use the same array that holds the configuration for the settings fields to register a contextual help panel to go with them. Just about everything needed to do this is already in place. Really I think I only need to add the support for the title and content options for the help screen and the proper callback for the content.
What do you think? Would that be cluttering the API?
I don’t see any reason not to include all of those options. The point of the class or functions set that you’re writing is to make it really easy to create the settings pages, and as far as I’m concerned, that includes contextual help tabs.
Just thought I’d drop a line to say that I just released the initial version of my settings API since you seemed interested if I was going to release it or not. I dropped the plans to add the support for the contextual help tabs, for now. Ran out of time. I needed to move on in the two projects that I’m going to utilize this API.
http://connections-pro.com/2012/07/11/connections-settings-api-wrapper-class-for-wordpress/
Available on GitHub.
https://github.com/shazahm1/Connections-Settings-API-Wrapper-Class
Let me know what you think.
Fantastic! I’ve left a comment with a couple of questions π
Very nice your method. I have used similar method to themes. I have a question. What is program are you using to record screencasts on Ubuntu? Thanks and congratulations.
Thanks, I’m glad you like it. I use the app call “RecordMyDesktop”. You can install it via the Ubuntu Software Center.
Hey Pippin,
I wanted to get your opinion on something. Using the same logic mentioned here (as far as setting up the options), I’m providing some defaults on-install like so: http://pastebin.com/mRsGpx4v The caveat I’m seeing in doing this is in the event I add-in a new option after the plugin has been installed once — the plugin then won’t update any new values I stick in there until the user re-saves the plugin options. In addition, that also makes it so I need to not only check the value of a plugin setting, but also make sure it is set in the first place. What would you recommend is the best way to handle this? I noticed you place the defaults in the plugin options themselves — but do you also run a isset() on them as well whenever they are used within the plugin — or is there a way to force a “re-save” on upgrade (not sure if there is such a function in WP) to use whatever settings are there by default? Thanks!
I usually run an isset().
Appreciate it Pippin – will do as well
Hey Pippin, somehow I missed this when you first published it. It’s in my Readability, but I mustn’t have gone back to read/watch. Anyway, I’ve rectified that now!
Really elegant solution here, I love to see this sort of thing π
Also, thanks for the Wptuts+ shout out in there. Tom has a written a few series that are really must-read reference material. This post should be too!
Thanks for stopping by Japh π
Hi Pippin, great tutorial,
My question is let’s assume I want to only display settings and save specific settings for each gateway separately.
Example: So at the top of the Gateway Tab, there would be a setting “Select your Gateway”
When “Paypal” is selected all the settings for Paypal would show, if we change to “Stripes” then all the settings for Stripes would show. This way the options page is clean and only settings for a specific gateway would show.
Any thoughts?
Kyle
You will need to pull in all of the settings for the gateways section:
To update just modify the array of data and then pass it back to update_option:
Love this! Using it to make my new version of my plugin extensible!
Glad to help!
What if you wanted to allow developers to add a new section to your settings? I’m struggling with this, because: I have multiple options that should be pulled from the database when settings are requested. Up to this point, an apply_filters-array containing these option_names would do. But then, say I need the same apply_filters-array in the function that deletes settings, that checks whether settings are available… In general, say I need it in multiple places. I tried to put in the construct of the main class, but it doesn’t work because it gets loaded too early while filters are applied too late… Any advice? Many thanks.
I think the best thing to do is just store all of your options in a single option key, that way it doesn’t matter if additional settings have been added to it.
Yes, that’s what I did in the end, even though I didn’t really like it as a solution being it not so neat and tidy, but thanks.
Pippin,
I am not seeing a video display. I can the videos on the other tutorials just not this one. I am running firefox 31 with no plugins.
Sorry about that. It is working now.