Justin Tadlock

Settings wrappers for plugins and themes

I’ve seen many methods of retrieving settings in themes and plugins over the years. Everything from an object property buried somewhere I can rarely find to a global variable wrapped by a function set up by a global variable.

Suffice it to say, I’ve seen it all.

Over time, I’ve developed my own system of retrieving settings by creating custom wrapper functions.

Why wrapper functions?

Generally, there are two calls theme or plugin authors might make to retrieve settings:

  • get_option()
  • get_theme_mod() (this is actually a wrapper for get_option())

I like to keep wrapper functions so that I’m not directly calling those functions in various parts of my code because:

  • Sometimes default values change.
  • Sometimes I need to change something about the setting itself.
  • I might add in some validation code.
  • There can be multiple calls to the same setting, which means I might make a mistake.
  • Other plugins or child themes may need to access the setting.

Having a dedicated wrapper function for settings helps alleviate any potential issues that might crop up.

Wrappers for theme mods

Because the Theme Mods API is already a wrapper for the core Options API, this is a bit simpler for themes. What I do with themes is create a dedicated wrapper function for each setting.

Let’s suppose I have a theme mod named color_primary. The call to it would look like the following.

get_theme_mod( 'color_primary', '#000000' );

To create a wrapper function for that, I simply do this:

function jt_get_color_primary() {

    return get_theme_mod( 'color_primary', '#000000' );
}

This way, any time I need to access the color, I use the jt_get_color_primary() function. Multiple calls would all share the same default #000000 value. And, if I ever wanted to do something like add an extra hook or run some other code over it, I’d only have to do it in one place.

Wrappers for plugin options

Plugin options (and themes that don’t utilize theme mods) require a different approach. I’m going to assume that the plugin is storing all of its settings as an array within a single database option.

There are three aspects to handling plugin options:

  • Setting up an array of defaults.
  • Creating a function similar to get_theme_mod() for your plugin.
  • Creating wrappers for individual settings.

Here’s how I create an array of default settings:

function jt_get_default_settings() {

    return array(
        // 1.0.0
        'example_a' => 'example',
        'example_b' => 'example',

        // 2.0.0
        'example_x' => 'example',
        'example_y' => 'example'
    );
}

I try to leave an inline comment for when new settings are added. So, I just drop in the version number.

The next thing to do is to create a function for grabbing individual settings, similar to what get_theme_mod() does for themes.

This function is very useful if you ever add new settings to your plugin and need for new defaults to work before the user has a chance to save them. I prefer this to having to run an update routine. _Note: This is the reason for the wp_parse_args() call._

function jt_get_setting( $setting ) {

    $defaults = jt_get_default_settings();
    $settings = wp_parse_args( get_option( 'jt_settings', $defaults ), $defaults );

    return isset( $settings[ $setting ] ) ? $settings[ $setting ] : false;
}

I like to add wrappers for individual settings as well. So, to get the example_a setting, I’ll add a wrapper function like so:

function jt_get_example_a() {

    return jt_get_setting( 'example_a' );
}

Conditional settings

Some settings have a limited set of accepted values and work great in conditionals. I might change it up a bit for these.

Let’s suppose we have a theme mod named layout_type to determine the type of layout. I might create a couple of functions for this, depending on my needs:

function jt_is_boxed_layout() {

    return 'boxed' === get_theme_mod( 'layout_type', $default_goes_here );
}

function jt_is_wide_layout() {

    return 'wide' === get_theme_mod( 'layout_type', $default_goes_here );
}

This helps keep some of the logic code out of theme templates.

The truth is that there’s a lot of variations you can do. They all depend on what you need and what type of data your setting is storing.

Hooks and other features

Some developers might want to add in extra hooks and such. I didn’t do this because core WP already has hooks for options. I also wanted to keep the code down to its basics for this tutorial. If you want to add in some extra hooks that are specific to your theme/plugin, go for it if you need to.

You can also run extra code within these functions, such as validation code. There are times when I do this; it just depends on what I need for a specific function and setting.

Strategies for long-term management

I don’t do this for every theme and plugin. It depends on how many settings I have and how those settings might be used by child themes or add-on plugins. If you only have two or three settings, you might not want to go this route.

However, if you have a large and complex plugin, having a dedicated options.php file where you define all of these would help out in long-term management. And, that’s my primary goal. I want to be able to not break stuff in the future and make it easy to figure out whenever I or someone else looks at the code.

Even if not following this exact method, create something that’s practical for both you and other developers who might use your code.

If you want to check out a real-world example, check out the function-options.php file from my Custom Content Portfolio plugin.