Option Arrays

In the Top 10 Most Common Coding Mistakes in WordPress Plugins, third on Ozh‘s list is “3. What? 87 new rows in the option table?”. In any of the plugins (and themes) I’ve looked at that use the built-in option saving functionality each field on the options page is being saved as a separate record in the options table.

These option pages can be written to save the plugin options as an array in a single record in the options table. This post is really a Part II to yesterday’s post, so I I’m going to use the Facebook Dashboard Widget options page for code samples.

In yesterday’s post I added a function that defined a whitelist array. For reference, here is the array:

$added = array( 'fdw_options' => array( 'fdw_showupdates',
'fdw_updatesfeed',
'fdw_updatesmax',
'fdw_updatesheight',
'fdw_updatesnewheight',
'fdw_updateswidth',
'fdw_shownotifications',
'fdw_notificationsfeed',
'fdw_notificationsmax',
'fdw_notificationsheight',
'fdw_notificationsnewheight',
'fdw_notificationswidth',
'fdw_showposted',
'fdw_postedfeed',
'fdw_postedmax',
'fdw_postedheight',
'fdw_postednewheight',
'fdw_postedwidth')
);

For each of the elements of the value array ( ‘fdw_showupdates’, ‘fdw_updatesfeed’, etc.) there is a corresponding field on the option form:


<select name="fdw_showupdates">
<option value="no"<?php if ( $fdw->updates_show == "no" ) { echo ' selected="selected"'; } ?>>No</option>
<option value="yes"<?php if ( $fdw->updates_show == "yes" ) { echo ' selected="selected"'; } ?>>Yes</option>
</select>

To implement as an array we need to come up with an option name. The one I chose was fb_dash_widget. To convert the field to be saved in that array I changed the name attribute to fd_dash_widget[showupdates]:


<select name="fd_dash_widget[showupdates]">
<option value="no"<?php if ( $fdw->updates_show == "no" ) { echo ' selected="selected"'; } ?>>No</option>
<option value="yes"<?php if ( $fdw->updates_show == "yes" ) { echo ' selected="selected"'; } ?>>Yes</option>
</select>

If all of the controls on the option form are named fd_dash_widget[unique_element_name] they will be posted by the browser as an element in the fd_dash_widget array. Once I made that change with all of the option fields on the form I updated the whitelist filter that I added yesterday:


function fdw_whitelist($options) {
$added = array( 'fdw_options' => array( 'fb_dash_widget' ) );
$options = add_option_whitelist( $added, $options );
return $options;
}
add_filter('whitelist_options', 'fdw_whitelist');

I haven’t had a chance to test it, but I expect a similar strategy could be used with theme options pages. A final note is that Chris, the author of the Facebook Dashboard Widget, left me a comment. So, I’ve been in contact with him and will be sending my revisions to him. At some point in the coming weeks, he should be releasing a new version.

About Ron

Homeschooling dad of 4 (ages 27 - 14), grampy to 3, WordPress core contributor, former farmboy & software developer by profession.

Comments

  1. I’ll have to check this out – we have been looking for something to integrate facebook into wpmu on another project.

    I love your idea of using areas instead of more entries into wp_options — too many things just take that “option” for granted.

    In a recent plugin we had done we had to store about 400 variables, and chose to write them to a .txt file vs the wp_options. but your array idea might be a better choice.

  2. Hi guys,

    I’ve been working on my own ecommerce plugin now for almost a year…

    It’s operational in v1 @ http://www.wenskaartenshop.be, v2 is now in test @ http://testground.wenskaartenshop.be, excuse the “spam”, but I’d love to hear some feedback from fellow WP lovers :)

    Now u can imagine an elaborate plugin like my ecommerce plugin requires an extensive list of options.

    The technique I used on my first plugin (WP Google Positioner) was to use 1 option array for all my plugins’ options, like described above.

    With my ecommerce plugin (which houses 8 widgets, full shopping cart and checkout, product catalog (with the new WP taxonomy system which I used for my “product” type) the full option list is about 150 items.

    Using a serialized TEXT (mysql) field was not a serious method to go with, as some option-values contain pieces of HTML code of about 500-1000 chars.

    As I have yet to cover the caching part of my plugin, my concern also lies with the amount of database queries I have to run on each page-load.
    As the product catalog is very extensive and has a “custom field” feature, and some categories contain more then 100 products, simple SQL selects would not cover the whole load without having to use too much queries.

    So I come to the point of my little story (I still hope to receive some feedback) :

    If you would need a large array of options, a technique you *could* use is:
    1. Prefix all your plugins’ options with something like ‘plugin_’
    2. Do a simple SQL: SELECT * FROM wp_options WHERE option_name LIKE ‘plugin_%’
    3. fetch the results and put in your plugin option class-property or variable.

    Hope to be of any assistance,

    Kim

    • Oops: forgot to say two things:

      1. while fetching the rows from the options table, don’t forget to maybe_unserialize() your option values!

      2. And the whole point of this: avoid doing too much get_option() calls.

      Greets

  3. webmaestro says:

    In some places you indicated ‘fb_dash_widget’, whilst in others you indicate ‘fd_dash_widget’… Thanks for the good stuff!

  4. The concept of the whitelist array never occurred to me! Wow. What a security hole if I don’t use it. Well, maybe not TOO bad, but still.

    Thanks for that. I learned the array tip from studying the Subscribe To Comments plugin and thought it was genius.