How To »

How to Build Your Own WordPress Widget

This post will describe the basic functions and methods for building a multi-widget with a customized intake form and sidebar widget display. The intended audience for this WP developers and front-end coders looking to enhance their knowledge of WP.

Widget Structure in Summary

Generate Sidebar Widget Template

  • Determine the widget instance
  • Get widget data based on current instance of the widget
  • Insert widget data into an HTML template for display in a sidebar

Generate Widget Form and Process Submitted Data

  • Determine the widget instance
  • Get any existing widget data based on current instance of the widget
  • Do some stuff to see which sidebar the widget should be displayed in
  • Foreach instance of the widget used in the sidebar, process any submitted data and update the values in the database
  • Display the widget options form with any existing data for current instance of the widget

Register the Widgets for use by WordPress

  • Determine the widget instance
  • Setup the unique widget details
  • Register each instance of the widget for use by WordPress

Add the Widget to the Widget Initializer in WordPress

The Core Widget Structure

  1. widgetname_widget();
  2. widgetname_widget_control();
  3. widgetname_widget_register();
  4. add_action(‘widgets_init’, widgetname_widget_register);

These four functions make up the core widget structure. The first function inserts the stored widget values into the HTML template for display in a sidebar.

widgetname_widget();

First, the function arguments are interpreted to determine the instance of the widget that is being used. The variable $number is extracted from $widget_args and is used throughout the function to target the current instance of the widget.

  1. function widgetname_widget$args, $widget_args = 1) {
  2.     extract( $args, EXTR_SKIP );
  3.     if ( is_numeric($widget_args) )
  4.         $widget_args = array( ‘number’ => $widget_args );
  5.     $widget_args = wp_parse_args( $widget_args, array( ‘number’ => -1 ) );
  6.     extract( $widget_args, EXTR_SKIP );

Then the values stored in the wp_options table are pulled using get_options('widgename_options'). The option name you use here will be used again in the other functions.

  1. $options = get_option(‘widgename_options’);
  2.     if ( !isset($options[$number]) ) return;

Next, put each widget value into a variable that will be used for the display in the widget HTML. Since the widget can have multiple instances, each with their own separate values, you have to call the option values by the instances number. So $options[$number] refers to the widget instance you are using.

  1. $title = $options[$number][‘title’];    // single value
  2. $text = $options[$number][‘text’];      // single value
  3. $check = $options[$number][‘check’];       // multi value
  4. $radio = $options[$number][‘radio’];       // single value
  5. $select = $options[$number][’select’];     // single value
  6. $textarea = $options[$number][‘textarea’]; // single value

Now you can just create an HTML template and echo the variables you just established. Because the widget form groups the checkboxes, the selected values are stored in an array and so each value is displayed through a foreach loop.

  1. echo $before_widget; // start widget display code
  2.     <h2><?=$title?></h2>
  3.     <p><?=$text?></p>
  4.      <ul>
  5.     <?php foreach($check as $value){ ?>
  6.         <li><?=$value?></li>
  7.     <?php } ?>
  8.     </ul>
  9.     <p><?=$radio?></p>
  10.     <p><?=$select?></p>
  11.     <p><?=$textarea?></p>       
  12. echo $after_widget; // end widget display code
  13. } // end widgetname_widget()

widgetname_widget_control();

This next function processes the data from the widget form or just displays the form if it’s the first time that widget instance has been created. So the first part of the function is just like the last. We determine which instance this widget is and extract the number as $number. Then you get the values, if any, using get_options('widgetname_options')

  1. function widgetname_widget_control($widget_args) {
  2.     global $wp_registered_widgets;
  3.     static $updated = false;
  4.     if ( is_numeric($widget_args) )
  5.         $widget_args = array( ‘number’ => $widget_args );                      
  6.     $widget_args = wp_parse_args( $widget_args, array( ‘number’ => -1 ) );
  7.     extract( $widget_args, EXTR_SKIP );
  8.        
  9.     $options = get_option(‘widgetname_options’);
  10.     if ( !is_array($options) ) $options = array();

This next bit does some stuff to decide if the widget is in the correct sidebar. There’s not much that needs to be touched here besides in Line 11, you need to put the name of the widget display function, where it says if ( 'widgetname_widget'.... On Line 13, you need to edit the widget id attribute value with a prefix based on your widget name for easy reference. !in_array( "widgetname-$widget_number"

  1. if ( !$updated && !empty($_POST[’sidebar’]) ) {
  2.     $sidebar = (string) $_POST[’sidebar’];     
  3.     $sidebars_widgets = wp_get_sidebars_widgets();
  4.                        
  5.     if ( isset($sidebars_widgets[$sidebar]) )
  6.         $this_sidebar =& $sidebars_widgets[$sidebar];
  7.     else
  8.         $this_sidebar = array();
  9.        
  10.     foreach ( (array) $this_sidebar as $_widget_id ) {
  11.         if ( ‘widgetname_widget’ == $wp_registered_widgets[$_widget_id][‘callback’] && isset($wp_registered_widgets[$_widget_id][‘params’][0][‘number’]) ) {
  12.             $widget_number = $wp_registered_widgets[$_widget_id][‘params’][0][‘number’];
  13.             if ( !in_array( "widgetname-$widget_number", $_POST[‘widget-id’] ) ) // the widget has been removed.
  14.                 unset($options[$widget_number]);
  15.             }
  16.     } // end foreach

Next, foreach instance of the widget you are adding to a sidebar, the data needs to be validated and added to the widget options array. $_POST['widgetname-value'] references the submitted form data. And foreach form that’s submitted we will store the data in $widgetname_value. In Line 2 here, we need to check if the form was canceled by testing for the ‘title’ value, or any other value you wish.

  1. foreach ( (array) $_POST[‘widgetname-value’] as $widget_number => $widgetname_value ) {
  2.     if ( !isset($widgetname_value[‘title’]) && isset($options[$widget_number]) ) // user clicked cancel
  3.         continue;

Now validate any of the data if necessary and store each value into another variable.

  1. $title = strip_tags(stripslashes($widgetname_value[‘title’]));
  2. $text = strip_tags(stripslashes($widgetname_value[‘text_value’]));
  3. $check = $widgetname_value[‘check_array’];
  4. $radio = $widgetname_value[‘radio_value’];
  5. $select = $widgetname_value[’select_value’];
  6. $textarea = $widgetname_value[‘textarea_value’];

Then, using the compact() function, we add each stored variable into the options array. Finally, the WP functionupdate_option() updates the database wp_options widget array.

  1. $options[$widget_number] = compact( ‘title’, ‘text’, ‘check’, ‘radio’, ’select’, ‘textarea’ );
  2.     }
  3.     update_option(‘widgename_options’, $options);
  4.     $updated = true;
  5. } // end foreach

The final stage of this control function is to generate the widget form and populate it with any existing values. So first, if it’s the first time this instance is being called, display an empty form. Otherwise, get the widget values corresponding to the current instance, identified by $options[$number].

  1. if ( -1 == $number ) { // if it’s the first time and there are no existing values
  2.     $title = ;
  3.     $text = ;
  4.     $check = ;
  5.     $radio = ;
  6.     $select = ;
  7.     $textarea = ;
  8.     $number = ‘%i%’;
  9. } else { // otherwise get the existing values
  10.     $title = attribute_escape($options[$number][‘title’]);
  11.     $text = attribute_escape($options[$number][‘text’]); // attribute_escape used for security
  12.     $check = $options[$number][‘check’];
  13.     $radio = $options[$number][‘radio’];
  14.     $select = $options[$number][’select’];
  15.     $textarea = format_to_edit($options[$number][‘textarea’]);
  16. }

Then display the form. This bit here shows how you can check if a value exist for a variety of form inputs.

  1. <p><label>Widget Title</label>
  2. <input id="title_value_<?php echo $number; ?>" name="widgetname-value[<?php echo $number; ?>][title]" type="text" value="<?=$title?>" /></p>
  3.     <p><label>Text Field</label>
  4. <input id="text_value_<?php echo $number; ?>" name="widgetname-value[<?php echo $number; ?>][text_value]" type="text" size="30" value="<?=$text?>" /></p>
  5.     <p>
  6.         <label>Checkbox Group</label>
  7.  
  8.         Value 1 <input id="check_array_<?php echo $number; ?>" name="widgetname-value[<?php echo $number; ?>][check_array][1]" type="checkbox" <?php if($check[1]){ echo ‘checked="checked"’;} ?> value="One" />
  9.  
  10.         Value 2 <input id="check_array_<?php echo $number; ?>" name="widgetname-value[<?php echo $number; ?>][check_array][2]" type="checkbox" <?php if($check[2]){ echo ‘checked="checked"’;} ?> value="Two" />
  11.  
  12.         Value 3 <input id="check_array_<?php echo $number; ?>" name="widgetname-value[<?php echo $number; ?>][check_array][3]" type="checkbox" <?php if($check[3]){ echo ‘checked="checked"’;} ?> value="Three" />
  13.  
  14.         Value 4 <input id="check_array_<?php echo $number; ?>" name="widgetname-value[<?php echo $number; ?>][check_array][4]" type="checkbox" <?php if($check[4]){ echo ‘checked="checked"’;} ?> value="Four" />
  15.     </p>
  16.     <p>
  17.         <label>Radio Field</label>
  18.  
  19.         Yes <input id="radio_value_<?php echo $number; ?>" name="widgetname-value[<?php echo $number; ?>][radio_value]" type="radio" <?php if($radio == ‘yes’) echo ‘checked="checked"’; ?> value="yes" />
  20.         No <input id="radio_value_<?php echo $number; ?>" name="widgetname-value[<?php echo $number; ?>][radio_value]" type="radio" <?php if($radio == ‘no’) echo ‘checked="checked"’; ?> value="no" />
  21.     </p>
  22.     <p>
  23.         <label>Select Menu
  24.         <select id="select_value_<?php echo $number; ?>" name="widgetname-value[<?php echo $number; ?>][select_value]">
  25.             <option <?php if ($select == ‘One’) echo ’selected’; ?> value="One">Value 1</option>
  26.             <option <?php if ($select == ‘Two’) echo ’selected’; ?> value="Two">Value 2</option>
  27.             <option <?php if ($select == ‘Three’) echo ’selected’; ?> value="Three">Value 3</option>
  28.             <option <?php if ($select == ‘Four’) echo ’selected’; ?> value="Four">Value 4</option>
  29.         </select>
  30.         </label>
  31.     </p>
  32.     <p><label>Textarea</label>
  33. <textarea id="textarea_value_<?php echo $number; ?>" name="widgetname-value[<?php echo $number; ?>][textarea_value]" type="text" cols="30" rows="4"><?=$textarea?></textarea></p>
  34.     <input type="hidden" name="widgetname-value[<?php echo $number; ?>][submit]" value="1" />
  35.  

widgetname_widget_register();

This function sets up the widget to be recognized by WP and gives the widget it’s identifying details. First we get the widget values through the get_option('widgetname_options')

  1. function widgetname_widget_register() {
  2.     if ( !$options = get_option(‘widgetname_options’) )
  3.         $options = array();

Then add the necessary details to identify your widget.

  1. $widget_ops = array(
  2.     ‘classname’ => ‘widgetname’,
  3.     ‘description’ => __(‘Widgetname Description’)
  4. );
  5. $control_ops = array(
  6.     ‘width’ => 400,
  7.     ‘height’ => 350,
  8.     ‘id_base’ => ‘widgetname’);
  9. $name = __(‘Widget Name’);

This next and final bit is important, but it just requires the correct editing with your widget function names and id prefixes. The id prefix isn’t required to be anything other than an identifier, so it doesn’t have to be anything in particular other than some form of the widget name.

  1. $id = false;
  2. foreach ( (array) array_keys($options) as $o ) {
  3.     if ( !isset( $options[$o][‘title’] ) )
  4.         continue;
  5.     $id = "widgetname-$o";
  6.     wp_register_sidebar_widget($id, $name, ‘widgetname_widget’, $widget_ops, array( ‘number’ => $o ));
  7.     wp_register_widget_control($id, $name, ‘widgetname_widget_control’, $control_ops, array( ‘number’ => $o ));
  8. } // end foreach
  9.                
  10. if ( !$id ) {
  11.     wp_register_sidebar_widget( ‘widgetname-1′, $name, ‘widgetname_widget’, $widget_ops, array( ‘number’ => -1 ) );
  12.     wp_register_widget_control( ‘widgetname-1′, $name, ‘widgetname_widget_control’, $control_ops, array( ‘number’ => -1 ) );
  13.     }
  14. }

Finally, and most importantly, use the add_action() function to add the widget with the other WP widgets using the ‘widgets_init’ hook. The ‘1′ at the end of the arguments is used to set the placement of the widget in the Available Widgets list seen at the Widgets page in Wordpress.

  1. add_action(‘widgets_init’, widgetname_widget_register, 1);

Johnathan Andersen Design Simple Widget Plugin

Get the entire function set described above in this simple plugin. The plugin simple, blank widget with a text field, checkbox, radio button, select menu, and textarea for you to hack around with. This should be a great learning tool on how to customize your widget. It is based off the current WordPress widget function structure and should be pretty easy to work with.

Compatible with WordPress 2.7.x. Feel free to test is on previous widgetized versions and report back.

Download JAD Simple Widget

See an example of the widget in action.

picture-2

Let me know if you have any questions or suggestions on how to better document this plugin. Thanks!

I take no responsibility if this plugin breaks anything. It didn’t break anything for me, so it should be fine. But let me know if it does anything unexpected.

Comments are closed.