Saving Wordpress Plugin Options – Admin Panels Done Right

This isn’t a terribly difficult task – it’s incredibly common, and it’s covered multiple places in the codex. So why am I writing about it? A few months ago, I was tasked with customizing a plugin – one that someone else wrote. I need to add some options to it, and their code was baffling to me. I could see that they were using custom options, but I couldnt understand how they were being set – it was like the author just made some form fields and hoped for the best.

More Wordpress Magic

What was happening is referenced here (Right in the codex – apparently the last place I thought to look). My first instinct has always been to post forms on an admin page to itself, then handle checking for the $_POST values, and creating/updating the appropriate options. As is often the case, WordPress makes it even easier than that:

Set Up Your Form Properly

I wont get into the boring details – you can look at the codex page for that – but pay special attention to the hidden fields you set up:


<input name="action" type="hidden" value="update" />
<input name="page_options" type="hidden" value="new_option_name,some_other_option,option_etc" />

Not too tough to understand – the first line tells the system that we’re going to be updating, and the second line lets WordPress know which fields we want to create/update.  These, of course, need to match the “name” attribute of the input elements up above.

But What About Arrays?

I posted a few days ago about the very cool functionality of maybe_serialize(), and its relation to WordPress options.  I often store arrays in options, because they help keep the database free of unnecessary clutter, and they make your plugin even easier to use (from a developers view).  I was a little worried that this “page options” trick would prevent me from saving arrays – but alas, WordPress saved the day again:


<input type="text" name="fruit_colors['apple']" value="red">
<input type="text" name="fruit_colors['carrot']" value="orange">
<input type="text" name="fruit_colors['banana']" value="yellow">

Just make a form field an array, like you would with a set of checkboxes (by adding [] after it).  Pass in the proper values to the page_option hidden field, like so:


<input name="page_options" type="hidden" value="fruit_colors" />

This can get pretty interesting – a few days ago I used to to loop through categories and associate a string with each one – you can do the same for posts, days of the week, whatever suits your plugin.

So there you go.  You’ve got yourself an option without any tinkering with $_POST variables, or checking if you need to update or create an option.  Wordpress even takes care of serializing it for you.  What a world…

4 Comments »

4 Comments

  1. The only problem with this approach is validation of the data that the user enters. You don’t get to do any. I usually just check for the appropriate $_POST variable in init, save the options appropriately, and then use a redirect to the admin page with an $_GET variable indicating an update happened.

  2. You’re right Nick – letting WordPress do all the dirty work precludes the ability to do any real validation, or fancy manipulation. However, for most admin panels, I’ve found that it still works ok.

    I’m intrigued by your approach though – I definitely like the idea of using a $_GET variable to indicate an update, as it’s always helpful to tell the user what has been updated. I’m a little skeptical about running it on init though – since init runs on every page load, both front and back, we’re adding the extra overhead of checking for the $_POSTed variable on every page load – even ajax calls. Also – depending on what you’re doing, you’ll need to do some extra validation to make sure the call is coming from the right place, and whoever is making the call has the proper permissions to do so (again, because running from init, it could be accessible from the front end).

    If I do need to do some extra data manipulation on posted variables from an admin page, I usually opt to put the code at the top of my admin panel display function, and post the form to itself with action=”". That way, I know the code is only going to be run from that particular admin page, and anybody trying to get to it from outside will have to deal with WordPress’ authentication functions.

    I’d be interested to hear if I’m way off base with this though (heck, I’d be interested to hear if I’m even a little off base), and your thoughts about my concerns on running on init. New ideas always help, and you definitely seem to know what you’re talking about.

    Either way, thanks for stopping by and commenting!

  3. To be honest, a simple if statement on a value available globally isn’t going to be a bottleneck at all compared to all the other stuff that goes on when WP loads. Also, you can hook to admin_init to make sure it only happens on admin page loads.

    To make sure that the correct form is also getting submitted and the user actually was accessing the form, you can use a combination of ‘check_admin_referer’ and ‘current_user_can’. I initially left those out of my description because I didn’t really feel like bogging down my approach. You should be using those things anyways, though, regardless of how you check for submission.

  4. Well played. You’re probably right about the reality of the processing power of performing a single if statement on init – but I think there will always be a little voice in my head yelling every time I do it when I don’t absolutely have to :) .

    You also raise some valid points about using current_user_can – I often forget that many WordPress users take advantage of roles – it’s important to make sure you’re not giving too much power to the underlings.

Leave a Reply