How to Write a Widget in WordPress 3

Exclusive offer: get 50% off this eBook here
WordPress 3 Complete

WordPress 3 Complete — Save 50%

Create your own complete website or blog from scratch with WordPress

£14.99    £7.50
by April Hodge Silver | January 2011 | Open Source WordPress

WordPress is an excellent software that can run your website (blog or not). It's packed with excellent features, and is so flexible that it can really do anything you want, and it has a wealth of online resources. Additionally, it's super easy-to-use, and you need no special skills or prior experience to use it. Last but not least, it is free!

Writing a widget bears some similarities to writing a plugin, but in some ways it's easier because there is a widget class that you can leverage for some of the functionality. In this article by April Hodge Silver, author of WordPress 3 Complete, we will learn to write a widget in WordPress 3.

 

WordPress 3 Complete

WordPress 3 Complete

Create your own complete website or blog from scratch with WordPress

  • Learn everything you need for creating your own feature-rich website or blog from scratch
  • Clear and practical explanations of all aspects of WordPress
  • In-depth coverage of installation, themes, plugins, and syndication
  • Explore WordPress as a fully functional content management system
  • Clear, easy-to-follow, concise; rich with examples and screenshots
        Read more about this book      

(For more resources on Wordpress, see here.)

Recent posts from a Category Widget

In this section, we will see how to write a widget that displays recent posts from a particular category in the sidebar. The user will be able to choose how many recent posts to show and whether or not to show an RSS feed link. It will look like the following screenshot:

WordPress 3 Complete

Let's get started!

Naming the widget

Widgets, like plugins, need to have a unique name. Again, I suggest you search the Web for the name you want to use in order to be sure of its uniqueness. Because of the widget class, you don't need to worry so much about uniqueness in your function and variable names, since the widget class unique-ifies them for you.

I've given this widget the filename ahs_postfromcat_widget.php.

As for the introduction, this comment code is the same as what you use for the plugin. For this widget, the introductory comment is this:

/*
Plugin Name: April's List Posts Cat Widget
Plugin URI: http://springthistle.com/wordpress/plugin_postfromcat
Description: Allows you to add a widget with some number of most recent posts from a particular category
Author: April Hodge Silver
Version: 1.0
Author URI: http://springthistle.com
*/

Widget structure

When building a widget using the widget class, your widget needs to have the following structure:

class UNIQUE_WIDGET_NAME extends WP_Widget {

function UNIQUE_WIDGET_NAME() {
$widget_ops = array();
$control_ops = array();
$this->WP_Widget();
}

function form ($instance) {
// prints the form on the widgets page
}

function update ($new_instance, $old_instance) {
// used when the user saves their widget options
}

function widget ($args,$instance) {
// used when the sidebar calls in the widget
}

}

// initiate the widget

// register the widget

Of course, we need an actual unique widget name. I'm going to use Posts_From_Category. Now, let's flesh out this code one section at a time.

Widget initiation function

Let's start with the widget initiation function. Blank, it looks like this:

function Posts_From_Category() {
$widget_ops = array();
$control_ops = array();
$this->WP_Widget();
}

In this function, which has the same name as the class itself and is therefore the constructor, we initialize various things that the WP_Widget class is expecting. The first two variables, to which you can give any name you want, are just a handy way to set the two array variables expected by the third line of code.

Let's take a look at these three lines of code:

  • The $widget_ops variable is where you can set the class name, which is given to the widget div itself, and the description, which is shown in the WP Admin on the widgets page.
  • The $control_ops variable is where you can set options for the control box in the WP Admin on the widget page, like the width and height of the widget and the ID prefix used for the names and IDs of the items inside.
  • When you call the parent class' constructor, WP_Widget(), you'll tell it the widget's unique ID, the widget's display title, and pass along the two arrays you created.

For this widget, my code now looks like this:

function Posts_From_Category() {
$widget_ops = array(
'classname' => 'postsfromcat',
'description' => 'Allows you to display a list of
recent posts within a particular category.');

$control_ops = array(
'width' => 250,
'height' => 250,
'id_base' => 'postsfromcat-widget');

$this->WP_Widget('postsfromcat-widget', 'Posts from a Category', $widget_ops, $control_ops );
}

Widget form function

This function has to be named form(). You may not rename it if you want the widget class to know what it's purpose is. You also need to have an argument in there, which I'm calling $instance, that the class also expects. This is where current widget settings are stored.

This function needs to have all of the functionalities to create the form that users will see when adding the widget to a sidebar. Let's look at some abbreviated code and then explore what it's doing:

<?php
function form ($instance) {

$defaults = array('numberposts' => '5','catid'=>'1','title'=>'','rss'=>'');
$instance = wp_parse_args( (array) $instance, $defaults ); ?>

<p>
<label for="<?php echo $this->get_field_id('title'); ?>">Title:</label>
<input type="text" name="<?php echo $this->get_field_name('title') ?>" id="<?php echo $this->get_field_id('title') ?> " value="<?php echo $instance['title'] ?>" size="20"> </p>

<p>
<label for="<?php echo $this->get_field_id('catid'); ?>">Category ID:</label>
<?php wp_dropdown_categories('hide_empty=0&hierarchical=1&id='.$this->get_field_id('catid').'&name='.$this->get_field_name('catid').'&selected='.$instance['catid']); ?>
</p>

<p>
<label for='<?php echo $this->get_field_id('numberposts'); ?>">Number of posts:</label>
<select id="<?php echo $this->get_field_id('numberposts'); ?>" name="<?php echo $this->get_field_name('numberposts'); ?>">
<?php for ($i=1;$i<=20;$i++) {
echo '<option value="'.$i.'"';
if ($i==$instance['numberposts']) echo ' selected="selected"';
echo '>'.$i.'</option>';
} ?>
</select>
</p>

<p>
<input type="checkbox" id="<?php echo $this->get_field_id('rss'); ?>" name="<?php echo $this->get_field_name('rss'); ?>" <?php if ($instance['rss']) echo 'checked="checked"' ?> />
<label for="<?php echo $this->get_field_id('rss'); ?>">Show RSS feed link?</label>
</p>

<?php
}
?>

First, I set some defaults, which in this case is just for the number of posts, which I think it would be nice to set to 5. You can set other defaults in this array as well.

Then you use a WordPress function named wp_parse_args(), which creates an $instance array that your form will use. What's in it depends on what defaults you've set and what settings the user has already saved.

Then you create form fields. Note that for each form field, I make use of the built-in functions that will create unique names and IDs and input existing values.

  • $this->get-field_id creates a unique ID based on the widget instance (remember, you can create more than one instance of this widget).
  • $this->get_field_name() creates a unique name based on the widget instance.
  • The $instance array is where you will find the current values for the widget, whether they are defaults or user-saved data.

All the other code in there is just regular PHP and HTML. Note that if you give the user the ability to set a title, name that field "title", WordPress will show it on the widget form when it's minimized. The widget form this will create will look like this:

WordPress 3 Complete

 

WordPress 3 Complete Create your own complete website or blog from scratch with WordPress
Published: January 2011
eBook Price: £14.99
Book Price: £24.99
See more
Select your format and quantity:

 

        Read more about this book      

(For more resources on Wordpress, see here.)

Widget save function

When a user clicks the save button on the widget form, WordPress uses AJAX to run your save function. You need to be sure to save whatever the user types in, which is all we're doing in this case, but you can put other functionalities here if it's appropriate for your widget (for example, database interactions, conversions, calculations, and so on). The final code for this function is as follows:

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

$instance['catid'] = $new_instance['catid'];
$instance['numberposts'] = $new_instance['numberposts'];
$instance['title'] = $new_instance['title'];
$instance['rss'] = $new_instance['rss'];

return $instance;
}

Be sure this function is named update() and is prepared to accept two instances, one with old data and one with the just-submitted data. You can write your code to check the $new_instance for problems, and thus return the $old_instance if the new one isn't valid. The $instance you return will be what's shown in the update widget form.

Widget print function

The third main function in your widget class is the one that is called by the sidebar when it's time to actually show the widget to people visiting the website. It needs to retrieve any relevant saved user data and print out information for the website visitor. In this case, our final print function looks like this:

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

$title = $instance['title'];
$catid = $instance['catid'];
$numberposts = $instance['numberposts'];
$rss = $instance['rss'];

global $wpdb;
$posts = get_posts('numberposts='.$numberposts.'&category='.$catid);
$out = '<ul>';
foreach($posts as $post) {
$out .= '<li><a href="'.get_permalink($post->ID).'">'.$post->post_title.'</a></li>';
}
if ($rss) $out .= '<li><a href="'.get_category_link($catid).'feed/" class="rss">Category RSS</a></li>';
$out .= '</ul>';

echo $before_widget;
echo $before_title.$title.$after_title;
echo $out;
echo $after_widget;
}

The first thing I do is extract the data in the instance, which has the information the website administrator had saved when filling out the widget form. Then, the widget contacts the database to get the posts in the category and prints them out in a nice bulleted list.

The last four lines are important. There are four variables that the theme developer set when activating the sidebar as a widget-ready area. We set them ourselves. They are:

  • $before_widget
  • $before_title
  • $after_title
  • $after_widget

Be sure to use those so that theme developers are happy with your widget.

Initiate and hook up the widget

That's it for widget functionality! Now you just need to add a little code that will hook the widget up to the rest of WordPress.

function ahspfc_load_widgets() {
register_widget('Posts_From_Category');
}

add_action('widgets_init', 'ahspfc_load_widgets');

This tells WordPress that when it initiates widgets, it should be sure to register our new widget.

Final widget code

Here is the complete widget code:

<?php
/*
Plugin Name: April's List Posts Cat Widget
Plugin URI: http://springthistle.com/wordpress/plugin_postfromcat
Description: Allows you to add a widget with some number of most recent posts from a particular category
Author: April Hodge Silver
Version: 1.0
Author URI: http://springthistle.com
*/

class Posts_From_Category extends WP_Widget {

function Posts_From_Category() {
/* Widget settings. */
$widget_ops = array(
'classname' => 'postsfromcat',
'description' => 'Allows you to display a list of recent posts within a particular category.');

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

/* Create the widget. */
$this->WP_Widget('postsfromcat-widget', 'Posts from a Category', $widget_ops, $control_ops );
}

function form ($instance) {
/* Set up some default widget settings. */
$defaults = array('numberposts' => '5','catid'=>'1','title'=>'','rss'=>'');
$instance = wp_parse_args( (array) $instance, $defaults ); ?>

<p>
<label for="<?php echo $this->get_field_id('title'); ?>">Title:</label>
<input type="text" name="<?php echo $this->get_field_name('title') ?>" id="<?php echo $this->get_field_id('title') ?> " value="<?php echo $instance['title'] ?>" size="20">
</p>

<p>
<label for="<?php echo $this->get_field_id('catid'); ?>">Category ID:</label>
<?php wp_dropdown_categories('hide_empty=0&hierarchical=1&id='.$this->get_field_id('catid').'&name='.$this->get_field_name('catid').'&selected='.$instance['catid']); ?>
</p>

<p>
<label for="<?php echo $this->get_field_id('numberposts'); ?>">Number of posts:</label>
<select id="<?php echo $this->get_field_id('numberposts'); ?>" name="<?php echo $this->get_field_name('numberposts'); ?>">
<?php for ($i=1;$i<=20;$i++) {
echo '<option value="'.$i.'"';
if ($i==$instance['numberposts']) echo ' selected="selected"';
echo '>'.$i.'</option>';
} ?>
</select>
</p>

<p>
<input type="checkbox" id="<?php echo $this->get_field_id('rss'); ?>" name="<?php echo $this->get_field_name('rss'); ?>" <?php if ($instance['rss']) echo 'checked="checked"' ?> />
<label for="<?php echo $this->get_field_id('rss'); ?>">Show RSS feed link?</label>
</p>

<?php
}

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

$instance['catid'] = $new_instance['catid'];
$instance['numberposts'] = $new_instance['numberposts'];
$instance['title'] = $new_instance['title'];
$instance['rss'] = $new_instance['rss'];

return $instance;
}

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

$title = $instance['title'];
$catid = $instance['catid'];
$numberposts = $instance['numberposts'];
$rss = $instance['rss'];

// retrieve posts information from database
global $wpdb;
$posts = get_posts('numberposts='.$numberposts.'&category='.$catid);
$out = '<ul>';
foreach($posts as $post) {
$out .= '<li><a href="'.get_permalink($post->ID).'">'.$post->post_title.'</a></li>';
}
if ($rss) $out .= '<li><a href="'.get_category_link($catid).'feed/" class="rss">Category RSS</a></li>';
$out .= '</ul>';

//print the widget for the sidebar
echo $before_widget;
echo $before_title.$title.$after_title;
echo $out;
echo $after_widget;
}
}

function ahspfc_load_widgets() {
register_widget('Posts_From_Category');
}

add_action('widgets_init', 'ahspfc_load_widgets');

?>

Trying out the widget

Your widget is ready to go! Save all of your changes, and upload your widget to wp-content/plugins. Go to the Installed Plugins page, and you'll see your widget waiting to be activated:

WordPress 3 Complete

Activate it, and then navigate to Appearance | Widgets. You'll see the widget waiting to be added to a sidebar:

WordPress 3 Complete

Drag the widget to a sidebar, and then click on the little down arrow to edit it. You'll see the options slide down, as shown in the following image:

WordPress 3 Complete

You can enter a Title or leave it blank for the default, choose the Category to use, choose the Number of posts, and choose whether or not to Show RSS feed link. Then click on Save as you would with any widget. When you return to the frontend of the site and reload, posts from the category you chose are displayed in the sidebar as follows:

WordPress 3 Complete

Summary

In this article, you learned everything you needed to know about creating basic widgets. Now you know how to structure the PHP file and where to put your functions. You also learned about adding management pages and enabling widgets to have database access.


Further resources on this subject:


WordPress 3 Complete Create your own complete website or blog from scratch with WordPress
Published: January 2011
eBook Price: £14.99
Book Price: £24.99
See more
Select your format and quantity:

About the Author :


April Hodge Silver

April has been designing and developing new web sites from scratch since 1999, just before her graduation from Columbia University. Early in her career, she worked for several web companies and startups, including DoubleClick and About.com. Since 2004, she has been self-employed through her company Springthistle Design and has worked with a staggering variety of companies, non-profits, and individuals to realize their web site dreams. In her professional work, April's focus is always on usability, efficiency, flexibility, clean design, and client happiness. WordPress is the best solution for many of Springthistle's Clients, though April also develops custom web applications using PHP and MySQL. More about April's professional work at http://springthistle.com

In her free time, April enjoys developing recipes in the kitchen, bicycling, and relaxing with her daughter, dog, and darlin wife.

Books From Packt


WordPress Plugin Development: Beginner's Guide
WordPress Plugin Development: Beginner's Guide

WordPress 3.0 jQuery
WordPress 3.0 jQuery

WordPress 3 Site Blueprints
WordPress 3 Site Blueprints

WordPress 2.8 Themes Cookbook
WordPress 2.8 Themes Cookbook

WordPress Complete
WordPress Complete

WordPress 3.0 Ultimate Security
WordPress 3.0 Ultimate Security

WordPress and Flash 10x Cookbook
WordPress and Flash 10x Cookbook

WordPress MU 2.8: Beginner's Guide
WordPress MU 2.8: Beginner's Guide


Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software