The complete guide to creating widgets in WordPress 2.8

I have seen some good tutorials on creating widgets for WordPress 2.8 floating around the WordPress-o-Sphere. But, I didn’t feel any of them really covered practical usage. I want to show you how to create a widget for real-world development using WordPress 2.8’s new widget class.

In this tutorial, I’ll walk you through the steps of setting up a widget, its settings form, and displaying it on your site. At the end of the tutorial, you can download an example plugin to build from. Of course, you can apply this to your themes as well.

If you don’t feel like reading through the tutorial, skip to the end and download the example widget. It’s heavily commented and will give you a good base to build from.

What will the example widget do?

For the sake of the tutorial, we’ll be creating something extremely simple, yet you’ll see some advanced techniques on how to give users more control over the display of the widget through the widget controls.

Our widget will display a person’s name and sex. The controls will allow for the input of a widget title (text input), the input of the user’s name (text input), the selection of the person’s sex (select box), and whether the sex should be shown publicly (checkbox).

Here’s what the output of the widget will look like:

Example Widget Display

I know, it’s not much, but you’ll be able to take these tools and apply them to more complex widgets.

Loading the widget at the appropriate time

The first thing we have to do is load our widget when necessary. WordPress provides the widgets_init action hook that will allow us to do this. In WordPress 2.8, this action hook is fired right after the default WordPress widgets have been registered.


/* Add our function to the widgets_init hook. */
add_action( 'widgets_init', 'example_load_widgets' );

/* Function that registers our widget. */
function example_load_widgets() {
	register_widget( 'Example_Widget' );

If you wanted to create more than one widget, you’d use the register_widget() function for each widget inside of the example_load_widgets() function.

Setting up our widget

In the past, creating widgets in WordPress was some ugly mish-mash of functions that was incomprehensible. In 2.8, we simply have to extend the preexisting WP_Widget class. So, the first step is creating a new class with a unique name.

class Example_Widget extends WP_Widget {

Then, we’ll want to add our first function. This function will be what makes our widget unique to WordPress, and it’ll allow us to set up the widget settings.

Note that the class name and first function name are the same. In this example this is Example_Widget.

	function Example_Widget() {
		/* Widget settings. */
		$widget_ops = array( 'classname' => 'example', 'description' => 'An example widget that displays a person\'s name and sex.' );

		/* Widget control settings. */
		$control_ops = array( 'width' => 300, 'height' => 350, 'id_base' => 'example-widget' );

		/* Create the widget. */
		$this->WP_Widget( 'example-widget', 'Example Widget', $widget_ops, $control_ops );

You’ll want to make some of this stuff unique to your widget.

Displaying the widget

The next function within our Example_Widget class will handle the display of the widget. This code might be a little confusing because we don’t know what it all means (we haven’t added the controls).

The goal here is to take the settings supplied by what the user selected for the widget and display the widget according to those values.

It’s also important to make sure you use the $before_widget, $after_widget, $before_title, and $after_title variables. These are provided by the theme and should not be hardcoded. How widgets are displayed should always be handled by the theme.

	function widget( $args, $instance ) {
		extract( $args );

		/* User-selected settings. */
		$title = apply_filters('widget_title', $instance['title'] );
		$name = $instance['name'];
		$sex = $instance['sex'];
		$show_sex = isset( $instance['show_sex'] ) ? $instance['show_sex'] : false;

		/* Before widget (defined by themes). */
		echo $before_widget;

		/* Title of widget (before and after defined by themes). */
		if ( $title )
			echo $before_title . $title . $after_title;

		/* Display name from widget settings. */
		if ( $name )
			echo '<p>Hello.  My name is' . $name . '.</p>';

		/* Show sex. */
		if ( $show_sex )
			echo '<p>I am a ' . $sex . '.</p>';

		/* After widget (defined by themes). */
		echo $after_widget;

Making sure our widget is updated and saved

In this step, we’ll take each of our widget settings and save them. It’s a pretty simple procedure. We’re just updating the widget to use the new user-selected values.

If you’re using something like a text input in your form and users shouldn’t add XHTML to it, then you should add the value to the strip_tags() function as shown below.

	function update( $new_instance, $old_instance ) {
		$instance = $old_instance;

		/* Strip tags (if needed) and update the widget settings. */
		$instance['title'] = strip_tags( $new_instance['title'] );
		$instance['name'] = strip_tags( $new_instance['name'] );
		$instance['sex'] = $new_instance['sex'];
		$instance['show_sex'] = $new_instance['show_sex'];

		return $instance;

Creating widget controls or settings

The reason the new widget class in WordPress 2.8 is so cool is how easy it is to set up controls for your widgets. The get_field_id() and get_field_name() functions handle most of the dirty work, leaving us to concentrate on more important things like actually creating the widget. Take special notice of how these functions are used because it’ll make life much simpler for you.

First, we might want to set up some defaults. By setting up defaults, we can control what’s shown just in case the user doesn’t select anything.

	function form( $instance ) {

		/* Set up some default widget settings. */
		$defaults = array( 'title' => 'Example', 'name' => 'John Doe', 'sex' => 'male', 'show_sex' => true );
		$instance = wp_parse_args( (array) $instance, $defaults ); ?>

The first two parts of the form will be text inputs: the widget title and the person’s name.

			<label for="<?php echo $this->get_field_id( 'title' ); ?>">Title:</label>
			<input id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" value="<?php echo $instance['title']; ?>" style="width:100%;" />

			<label for="<?php echo $this->get_field_id( 'name' ); ?>">Your Name:</label>
			<input id="<?php echo $this->get_field_id( 'name' ); ?>" name="<?php echo $this->get_field_name( 'name' ); ?>" value="<?php echo $instance['name']; ?>" style="width:100%;" />

The second part of the form will be a select box, allowing the user to select their sex.

			<label for="<?php echo $this->get_field_id( 'sex' ); ?>">Sex:</label>
			<select id="<?php echo $this->get_field_id( 'sex' ); ?>" name="<?php echo $this->get_field_name( 'sex' ); ?>" class="widefat" style="width:100%;">
				<option <?php if ( 'male' == $instance['format'] ) echo 'selected="selected"'; ?>>male</option>
				<option <?php if ( 'female' == $instance['format'] ) echo 'selected="selected"'; ?>>female</option>

The last part of the form will show a checkbox that allows the user to select whether they want to display their sex publicly.

			<input class="checkbox" type="checkbox" <?php checked( $instance['show_sex'], true ); ?> id="<?php echo $this->get_field_id( 'show_sex' ); ?>" name="<?php echo $this->get_field_name( 'show_sex' ); ?>" />
			<label for="<?php echo $this->get_field_id( 'show_sex' ); ?>">Display sex publicly?</label>

The only step left is closing off the form function and the rest of the widget code.


Time to create your own widgets

If you’ve ever created or attempted to create a widget in WordPress prior to 2.8, then you can probably see how much easier this is. To help people learn the new system, I’ve put together an example widget. I’ve left loads of comments about what code does what in the file, so it should be pretty easy to follow:

I’m enjoying working with the new widget class. I almost feel motivated to release a few new widgets in the near future. But, I’d love to see what all you come up with.