Introduction to using WordPress Options, part 2

This article is a continuation of the first introductory tutorial to the WordPress Options plugin. In this part 2 we’ll be looking at how you can take advantage of some of the power provided by the framework to create more complicated options setups. If you’re just starting out with the plugin please have a look at part 1.

Here’s what we will be addressing in this tutorial:

  1. Creating multiple options pages and sections
  2. Using extra options types to accept different kinds of data
  3. List of option types
  4. Using sets to limit value ranges and display custom dropdowns
  5. A brief look at the advanced callback mechanism

Creating multiple options pages and sections

Creating options pages and sections is very simple. They are represented in the framework as special options types that you can put at the top of your hierarchy of options. Let’s take the very basic example from part 1 and adjust it a little bit. To refresh your memory this is how the original snippet looked like:

$test_options = array(
	'show_tips' => array(
		'default' => false, 
		'label' => __('Show Tips', 'my-test')
	),
	'background_image' => array(
		'type' => 'image', 
		'label' => __('Background Image', 'my-test')
	),
	'header_logo_image' => array(
		'type' => 'image', 
		'label' => __('Logo Image', 'my-test'),
		'tip' => __('Maximum size is 1024x150 pixels', 'my-test')
	)
);

synved_option_register('my_test', $test_options);

Now suppose we want these same options to be exposed but this time we are working on a theme. Given it’s a theme we want the options to appear under the “Appearance” tab in the WordPress menu and we also want for the correct capability to be checked. Let’s modify the snippet above to do just that:

$test_options = array(
'page_appearance' => array(
	'type' => 'options-page',
	'label' => __('My Test', 'my-test'),
	'parent' => 'appearance',
	'role' => 'edit_theme_options',
	'sections' => array(
		'section_general' => array(
			'type' => 'options-section',
			'label' => __('General', 'my-test'),
			'tip' => __('General settings for the theme', 'my-test'),
			'settings' => array(
				'show_tips' => array(
					'default' => false, 
					'label' => __('Show Tips', 'my-test')
				),
				'background_image' => array(
					'type' => 'image', 
					'label' => __('Background Image', 'my-test')
				),
				'header_logo_image' => array(
					'type' => 'image', 
					'label' => __('Logo Image', 'my-test'),
					'tip' => __('Maximum size is 1024x150 pixels', 'my-test')
				)
			)
		)
	)
)
);

synved_option_register('my_test', $test_options);

As you can see we now have more hierarchical fine structure into our array but things under the settings attribute array have remained unchanged. If we examine the snippet in more detail we can notice we added an item at the top of the hierarchy with type attribute of “options-page”. This as you might expect creates an options page that can be placed anywhere in the WordPress admin menu.

Now we need to tell the framework where to put this new options page. We do this with the parent attribute. This attribute can take a value matching the lower-cased version of the admin menu tab you want the page to appear. For instance in this case we want the options page to appear under the Appearance tab in WordPress, so we use the value “appearance”. Alternatively you can use the same values as the $parent_slug parameter for the add_submenu_page function.

As I mentioned another requirement we had was to ensure modifying any options for this page had the correct capability. Given we are trying to expose these options for our theme the best pick in this case would be to use the edit_theme_options capability. So we can achieve this by simply specifying the role attribute for our options page and use the value “edit_theme_options”.

Capabilities can only be specified on an options page by options page basis and not on single specific options. This is a limitation of how the WordPress settings API works. Also note that setting capabilities is not really necessary. The plugin will figure out an appropriate capability for the options on its own, generally requiring the administrator role to edit any option. Selecting an appropriate capability might however provide a nice touch of usability for your users.

Using extra options types to accept different kinds of data

So far we have been limiting our array to 3 options and only 2 data options types, excluding of course the options-page and options-section types which are used to provide structure rather than direct data. The framework provides so far 15+ different data options types and more will be added as time goes by.

For instance suppose in addition to displaying an image logo in the header we also display some text there and we want the user to be able to select the color for the text. We can do this easily by adding an option like so:

$test_options = array(
'page_appearance' => array(
	'type' => 'options-page',
	'label' => __('My Test', 'my-test'),
	'parent' => 'appearance',
	'role' => 'edit_theme_options',
	'sections' => array(
		'section_general' => array(
			'type' => 'options-section',
			'label' => __('General', 'my-test'),
			'tip' => __('General settings for the theme', 'my-test'),
			'settings' => array(
				'show_tips' => array(
					'default' => false, 
					'label' => __('Show Tips', 'my-test')
				),
				'background_image' => array(
					'type' => 'image', 
					'label' => __('Background Image', 'my-test')
				),
				'header_logo_image' => array(
					'type' => 'image', 
					'label' => __('Logo Image', 'my-test'),
					'tip' => __('Maximum size is 1024x150 pixels', 'my-test')
				),
				'header_logo_color' => array(
					'type' => 'color', 
					'default' => '#333', 
					'label' => __('Logo Text Color', 'my-test'),
				)
			)
		)
	)
)
);

synved_option_register('my_test', $test_options);

As you can hopefully notice everything is the same as our previous snippet of code. The only thing we have changed is adding the “header_logo_color” option to the “settings” array. This extra option will expose a color picker interface for the user to select a custom color. We can then use the value of this option to output the color in some custom CSS we printed out somewhere on the page like this:

$color = synved_option_get('my_test', 'header_logo_color');
$mycss = '.header { color: ' . $color . '; }';
// Use $mycss somehwere

You might have noticed in the options array above for the header_logo_color option we specified an additional default attribute. What this does is it provides a fallback default value in case the user doesn’t specify one on his own. This way you can just retrieve the value of the option without having extra checks to ensure valid colors are used. This is in fact true for all options, which can specify a default value for when the user doesn’t set one on his own.

From the example above you may wonder if it’s safe to directly output the $color variable into our CSS or if this couldn’t cause parsing or even security problems if the value inserted by the user in the color field is in the wrong format. Rest assured that you don’t have to worry about value sanitation for your options as the framework takes care of it automatically.

In fact validation is a big part of the functionality provided by the framework and also why there are so many options types. These are not just used for generating the UI but also for validating the user input. That’s why it’s important to always use the correct option type depending on your needs.

List of option types

For your own reference this is the full list of all the different available options types so far, with a short description for each one:

  • boolean : a true/false value data type; displayed in the UI by a checkbox
  • integer : an integer value data type; displayed in the UI by a short edit field
  • decimal : a decimal value data type (generally in double precision); displayed in the UI by a short edit field
  • text : a string value data type; displayed in the UI by either an edit field or textarea depending on other attributes
  • color : a string value data type representing a color value; displayed in the UI by a short edit field with a custom color picker editor
  • image : a string value data type representing an image URL; displayed in the UI by en edit field with custom media item selector
  • video : a string value data type representing a video URL; displayed in the UI by en edit field with custom media item selector
  • media : a string value data type representing a media URL; displayed in the UI by en edit field with custom media item selector (note: at the moment image, video and media are equivalent)
  • page : a string value data type representing a single page; displayed in the UI by a dropdown selector of page names
  • user : a string value data type representing an user; displayed in the UI by a dropdown selector of user names
  • author : a string value data type representing an author; displayed in the UI by a dropdown selector of author names (for now same as user)
  • category : a string value data type representing a single category; displayed in the UI by a dropdown selector of category names
  • tag-list : for now still a string value data type representing a coma-separated list of tags; displayed in the UI by an edit field
  • style : a data type for usage as custom CSS style, for now just a string value; displayed in the UI by textarea
  • script : a data type for usage as custom JavaScript code, for now just a string value; displayed in the UI by textarea
  • addon : a string value data type representing a path to an installed addon; displayed in the UI by a button with custom upload interface to install the addon (note: provided by the addon installer)

Using sets to limit value ranges and display custom dropdowns

Sets are a mechanism the framework provides to define certain ranges of allowed values for a specific option. Sets can apply to options of type integer, decimal or text. A “linear” set, that is a set that has a limited and well defined list of possible values, will be represented in the UI as a dropdown.

Let’s take the example above and modify it a little bit to make use of this mechanism. Earlier we decided to add a color option for the logo text next to the option for the logo image. Maybe your theme doesn’t support the display of both a logo image and text so we want to allow the user to select which one he wants to display. To achieve that we can simply add a new text option with a set.

$test_options = array(
'page_appearance' => array(
	'type' => 'options-page',
	'label' => __('My Test', 'my-test'),
	'parent' => 'appearance',
	'role' => 'edit_theme_options',
	'sections' => array(
		'section_general' => array(
			'type' => 'options-section',
			'label' => __('General', 'my-test'),
			'tip' => __('General settings for the theme', 'my-test'),
			'settings' => array(
				'show_tips' => array(
					'default' => false, 
					'label' => __('Show Tips', 'my-test')
				),
				'background_image' => array(
					'type' => 'image', 
					'label' => __('Background Image', 'my-test')
				),
				'header_display_type' => array(
					'default' => 'logo_text', 'label' => __('Header Display Type', 'my-test'),
					'set' => 'logo_text=Logo Text,logo_image=Logo Image',
					'tip' => __('Select what content must be displayed in the header', 'my-test')
				),
				'header_logo_image' => array(
					'type' => 'image', 
					'label' => __('Logo Image', 'my-test'),
					'tip' => __('Maximum size is 1024x150 pixels', 'my-test')
				),
				'header_logo_color' => array(
					'type' => 'color', 
					'default' => '#333', 
					'label' => __('Logo Text Color', 'my-test'),
				)
			)
		)
	)
)
);

synved_option_register('my_test', $test_options);

As you can see we added the header_display_type option which only allows 1 of 2 specific values to be selected. Notice we didn’t specify a type for the option. The framework is smart enough to determine the type based on the value of the default attribute.

The set attribute is then specified as a string, a coma separating each set step and each step being formed by a unique key and an user friendly label. Alternatively for more complex sets you can use arrays, for instance to allow for translations. The code would look like this:

// [...]
				'header_display_type' => array(
					'default' => 'logo_text', 'label' => __('Header Display Type', 'my-test'),
					'set' => array(array('logo_text' => __('Logo Text', 'my-test')), array('logo_image' => __('Logo Image', 'my-test'))),
					'tip' => __('Select what content must be displayed in the header', 'my-test')
				),
// [...]

Note that when using arrays to define set you need to nest arrays for each of the “steps” that in the string form were separated by comas. This means creating a parent container array and then one array for each of the steps, which will then have a unique key to represent the value in code and then a user-friendly label as the value associated with the key and that will show up in the UI.

At this point you can use the new option defined above as every other option in the framework. In this case you would use the value of the option to determine whether to render a piece of text for the logo (like the site name or description) or the logo image that was selected in the other option:

$header_type = synved_option_get('my_test', 'header_display_type');

if ($header_type == 'logo_text') 
{
	$color = synved_option_get('my_test', 'header_logo_color');
	// render text
}
else if ($header_type == 'logo_image') 
{
	$image = synved_option_get('my_test', 'header_logo_image');
	// render image
}

A brief look at the advanced callback mechanism

The WordPress Options framework provides a nifty fully integrated callback mechanism that allows you to tweak and adjust dynamically how your options are presented and interact from an User Interface as well as a lower end validation perspectives. The mechanism allows the options framework to be dynamic and flexible while at the same time keeping it fairly simple.

The way the callback mechanism works is by allowing you to set almost any attribute or property in the options array to be dynamically retrieved from a callback instead of using a simple literal value. You do this by using a custom API function when setting the value of the attribute. Let’s look at a simple example.

Suppose your theme integrates with a specific third-party product, like an e-commerce plugin. You want to add an option that will allow the user to tweak the integration with this plugin but you don’t want users to see the option if they don’t have the extra plugin installed. The simplest way to do this will be setting the hidden attribute to a callback.

// [...]
				'custom_plugin_tweak' => array(
					'hidden' => synved_option_callback_create('!function_exists("custom_plugin_defined_function")'),
					'default' => false, 'label' => __('Custom Plugin Tweak', 'my-test'),
					'tip' => __('Force Custom Plugin to behave correctly with the them by unregistering its obsolete jQuery UI version', 'my-test')
				),
// [...]

In this case we are using the synved_option_callback_create function to create a callback very quickly based on some code. This is useful when you have a very simple and short piece of code. Otherwise if you have more code you can simply use the synved_option_callback function and pass in the actual callback as the first parameter. This can have the same form of an usual PHP and WordPress callback, i.e. either a function name or an array whose first element is an object and second element a method name to call on the object.

Conclusions

In this tutorial we covered quite a bit of ground on the plugin, even though a lot is still undiscussed and the framework provides a few more features, like custom value validation and sanitation as well as defining custom “styles” to customize the way the options look.

For these extra features and to get a better idea on the potential of the framework I highly recommend checking out our free theme Stripefolio and look into its functions.php file or also our other plugin WordPress Shortcodes provides some good examples on how to use the framework API.

facebooktwittergoogle_plusredditpinterestlinkedinmail
Posted In: Tutorials Tags: , , , , ,

8 Comments

  1. Ethan
    Posted October 23, 2012 at 9:15 pm | Permalink

    Ahh!! Much better! Thanks. Will study this…

  2. Jordan
    Posted May 18, 2013 at 7:28 pm | Permalink

    Thanks for the tutorial Elia, but I’m having a major problem. I added this code to my functions.php:
    $test_options = array(
    'page_appearance' => array(
    'type' => 'options-page',
    'label' => __('Website Polls', 'my-test'),
    'parent' => 'dashboard',
    'role' => 'edit_theme_options',
    'sections' => array(
    'section_general' => array(
    'type' => 'options-section',
    'label' => __('General', 'my-test'),
    'tip' => __('General settings for the theme', 'my-test'),
    'settings' => array(
    'homepage_poll_id' => array(
    'type' => 'text',
    'label' => __('Homepage Featured Poll ID', 'my-test'),
    'tip' => __('Only input the ID number, ex. 7792', 'my-test')
    ),

    'poll_id_1' => array(
    'type' => 'text',
    'label' => __('Daily Poll 1', 'my-test'),
    'tip' => __('Only input the ID number, ex. 7792', 'my-test'),
    ),

    'poll_id_2' => array(
    'type' => 'text',
    'label' => __('Daily Poll 2', 'my-test'),
    'tip' => __('Only input the ID number, ex. 7792', 'my-test'),
    ),

    'poll_id_3' => array(
    'type' => 'text',
    'label' => __('Daily Poll 4', 'my-test'),
    'tip' => __('Only input the ID number, ex. 7792', 'my-test'),
    ),

    'poll_id_4' => array(
    'type' => 'text',
    'label' => __('Daily Poll 5', 'my-test'),
    'tip' => __('Only input the ID number, ex. 7792', 'my-test'),
    ),

    )
    ))));

    synved_option_register('homepage_poll', $test_options);

    I do not see any errors from it on the site except when I try to activate a plugin I get this one:

    Fatal error: Call to undefined function synved_option_register() in /home/jspecs/public_html/wp-content/themes/gonzo/functions.php on line 525

    Any ideas why this is happening?

    Thanks in advance :)

    • elia
      Posted May 19, 2013 at 11:20 am | Permalink

      Have you included the synved-options package as stated in part 1 of the tutorial?

      • John Fontana
        Posted June 11, 2013 at 3:31 am | Permalink

        I am having this same problem. I included synved-options.php, and it works just fine by itself, but now I get that error whenever I try to update or install any other plugins.

        There is no file called synved-wp-options.php anywhere in the plugins folder…

        • elia
          Posted June 11, 2013 at 12:48 pm | Permalink

          You have to embed the plugin in your theme! Did you do that? That’s required in order to be sure the code will always run properly, even if the plugin is not installed separately. Look at part1 of the tutorial.

  3. John Fontana
    Posted June 11, 2013 at 3:59 am | Permalink

    Also, I am trying to create an option that uses a textarea — you mentioned that this is possible using the text option type listed above, but I can’t find how to do this. Even trying to search the plugin’s code for mentions of textarea…I would appreciate any help! Other than these glitches, I am very pleased with how quick and easy it is to instantly provide clients with theme options using this plugin. :-)

  4. John Fontana
    Posted June 11, 2013 at 4:37 am | Permalink

    I resolved the issues above:

    I used this around the call to synved_options_register, even though the tutorial said it wasn’t needed, and it prevented the error when activating/deactivating other plugins:

    if (function_exists(‘synved_option_register’))

    To use a texarea, I didn’t use the text type, but this code worked:

    ‘featured’ => array(
    ‘style’ => ‘extend’,
    ‘default’ => ”,
    ‘label’ => __(‘Home Page Featured’, ‘evolution’)
    )

    • elia
      Posted June 11, 2013 at 12:50 pm | Permalink

      Yes that’s the way you create a text area, by using the “text” type and the “extend” style.

      By the way the best way to see all the many options the framework provides at work it’s probably best to download one of our plugins, like our WordPress Social Media plugin.

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

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=""> <s> <strike> <strong>

Time limit is exhausted. Please reload the CAPTCHA.