Tutorials

Create a better ‘Recent Posts’ widget 0

I think everybody has used the ‘Recent Posts’ widget build into WordPress at some time. It’s a super simple widget that just does exactly what it says, it displays a list of the most recent posts.

But one of the problems I’ve been having with this widget, is the fact that it only displays posts from the ‘post’ posttype. There’s no way to specify a custom post type, so that’s when I decided to build my own, better, Recent Posts widget. And today I’m going to teach you how it’s done.

We start of with a standard template that I use with almost every plugin/widget I build.

[php]
<?php
/*
Plugin Name: RG Recent Posts
Plugin URI: http://robgloudemans.nl
Description: Display recent posts in a widget. Where the default widget only let’s you display recent posts of the ‘post’ posttype, with RG Recent Posts you can specify from which post type you want to display the recent posts.
Version: 1.0
Author: Rob Gloudemans
Author URI: http://robgloudemans.nl
*/

class RG_Recent_Posts extends WP_Widget{

public function __construct()
{
$params = array(
‘name’ => ‘RG Recent Posts’,
‘description’ => ‘Display recent posts in a widget. Specifiy which post type should be listed.’
);

parent::__construct(‘RG_Recent_Posts’, ”, $params);
}

public function form()
{

}

public function widget()
{

}

}

add_action(‘widgets_init’, function(){
register_widget(‘RG_Recent_Posts’);
});
[/php]

What it does is start of with the comments WordPress needs to recognize your plugin. You can specify the name, url and description of the plugin. See here for more information about the comment block for plugins.

After the comment block a new class is declared, this class extends the build in WP_Widget class. This way we get access to using the `form()` and `widget()` functions. The `form()` function is used to display the widget on the widget page of your WordPress Dashboard. The `widget()` function is used to display the widget in the sidebar of your website/blog.

Last thing the code does is hook into the `widget_init` action and register the widget.

When you put this code into `<yourwordpressroot>/wp-content/plugins` folder and activate the plugin through the Plugins page, you should already see the widget on the Widget page.

__construct function

First lets have a look at the construct function. Not very much special going on over here. What we do is call the `__construct()` function of the WP_Widget class and pass it three parameters. The first one is the ID of your widget. I usually give this the same name as my class. The second one is the name of the plugin and the third one are the parameters, the name and description of your plugin. Since we’re already giving the name via the `$param` array, it’s not necessary to fill the second parameter so we leave it blank.

[php]
public function __construct()
{
$params = array(
‘name’ => ‘RG Recent Posts’,
‘description’ => ‘Display recent posts in a widget. Specifiy which post type should be listed.’
);

parent::__construct(‘RG_Recent_Posts’, ”, $params);
}
[/php]

The form function

Next comes the `form()` function. As said before, this function is responsible for displaying the content of widget on the widget page of the WordPress Dashboard.

If you drag the widget into a sidebar right now, you’ll see the widget is empty.

The content of the widget is something we’ll have to program ourselves, with simple HTML.

[php]
public function form($instance)
{
extract($instance);
?>

<p>
<label for="<?=$this->get_field_id(‘title’);?>"><?= __(‘Title’);?>:</label>
<input
type="text"
class="widefat"
id="<?=$this->get_field_id(‘title’);?>"
name="<?=$this->get_field_name(‘title’);?>"
value="<?=(isset($title)) ? esc_attr($title) : ”;?>"
>
</p>

<p>
<label for="<?=$this->get_field_id(‘posttype’);?>"><?= __(‘Posttype’);?>:</label>
<input
type="text"
class="widefat"
id="<?=$this->get_field_id(‘posttype’);?>"
name="<?=$this->get_field_name(‘posttype’);?>"
value="<?=(isset($posttype)) ? esc_attr($posttype) : ”;?>"
>
</p>

<p>
<label for="<?=$this->get_field_id(‘num_posts’);?>"><?= __(‘Number of posts to show’);?>:</label>
<input
type="text"
size="3"
value="5"
id="<?=$this->get_field_id(‘num_posts’);?>"
name="<?=$this->get_field_name(‘num_posts’);?>"
value="<?=(isset($num_posts)) ? esc_attr($num_posts) : ”;?>"
>
</p>

<?php
}
[/php]

The form function takes one parameter, the data the user has saved. We give this variable the name `$instance`. To make it easier to work with this variables, we call the extract function, which just takes an array and takes every key/value pair and makes the value accessible with the key as the variable name.

Now we just use HTML and a few PHP functions to build the form. To get the styling right, we just have a look at the source code of WordPress and see that they wrap each label/input in a paragraph tag, also they give full width inputs a class of `widefat`. The small input we use for the post count gets the size attribute set to 3, just as the standard `Recent Posts` widget does.

We create 3 inputs, one for the title of the widget, a second one for the post type we want to display the recent posts of and one for the number of posts we want to show.

Let me explain a few functions that are used.

$this->get_field_id()

This function is available to use because we’re extending the WP_Widget class. This function generates a unique id for every input. You just pass it the id you would give the input and the function makes sure the id become unique, so it won’t clash with another id on the page. You also use this function on `for` attribute of the label, so when you click in the label, the input gets selected.

$this->get_field_name()

This function works exactly the same as the previous function but it makes sure the name parameter is also unique.

esc_attr()

We use this function to escape the variables we’ve gotten from the `extract()` function. Although it comes straight from WordPress and it should be safe, we’re better be safe than sorry, so we escape it anyway.

If you now save you work, refresh your Widget page and add the widget, it should look like this:

The widget function

The last function we need is the `widget()` function. This function is used to display the widget in the sidebars on you website/blog.

[php]
public function widget($args, $instance)
{
extract($args);
extract($instance);

echo $before_widget;
echo $before_title . $title . $after_title;

echo ‘<ul>’;

$posttype = ( ! empty($posttype)) ? $posttype : ‘post’;

$recentposts = new WP_Query(array(
‘post_type’ => esc_attr($posttype),
‘orderby’ => ‘date’,
‘order’ => ‘DESC’,
‘posts_per_page’ => esc_attr($num_posts),
‘ignore_sticky_posts’ => 1
));

if($recentposts->have_posts()) : while($recentposts->have_posts()) : $recentposts->the_post();?>

<li><a href="<?php the_permalink();?>"><?php the_title();?></a></li>

<?php endwhile; endif;

echo ‘</ul>’;

echo $after_widget;

}
[/php]

The widget function takes two parameters. The first one are the arguments that are specified when registering the sidebar.
The second parameter are the values that come we’re getting from the widget form that we’ve build with the previous function.

First we extract both of these variables again, so they’re easier to work with.

Next we begin echoing the widget. First we echo anything the user has specified as the ‘before_widget’ parameter of the register_sidebar function. Next we echo the title of the widget that we get from our widget form, wrapped in the `before_title` and `after_title` variables. Finally we echo the start of the unordered list that holds the recent posts.

Now it’s time to retrieve the posts from the post type that has been set.  First we check if a posttype has been set, if not, we set the post type to the default ‘post’ posttype.

The recent posts we get with a custom WordPress Loop. We use the `WP_Query` class for this. The constructor of this class can take a lot of parameters, but only a handful are useful to us.

First of all the posttype to retrieve, second is the parameter to order the post by and the third the sort order (ascending or descending).
The fourth parameter specifies the number of posts to retrieve and the fifth parameter specifies that only posts that have the ‘published’ status should be retrieved.
The last parameter makes sure that that so called ‘Sticky Posts‘ are ignored. If we would not set this parameter to TRUE, all sticky posts would show up in our recent posts, even if they are way older than ‘not-sticky’ posts.

NB. Setting this parameter to true doesn’t remove them from the results, it just makes sure they don’t show up at the top of the results.

Finally we loop over the results we’ve gotten and echo list items.

The only thing we have to do now is echo the closing tag of the unordered list and the value of the ‘after_widget’ variable. And our widget is finished.

Wrap it up

Within no time we’ve created our own ‘Recent Posts’ widget with the build in WP_Widget class. We’ve used a custom WordPress Loop to retrieve the results and have displayed them in a simple unordered list that should be styled like every other widget list cause it takes the styling set in the stylesheet of your theme.

Feel free to use this widget on your website or blog. Or maybe you want to extend it, things you could think about:

  • Change the posttype text input to a dropdown list with all defined posttypes
  • Give the user the ability to specify if sticky posts should be ignored or ignore certain other type of posts.

If you have any questions or would like to comment on this tutorial be free do drop a line in the comment section.