Create a Wordpress Recent-Posts Widget

May 17, 2007 | Published in: Wordpress & plugins | Tags: , , , , , , 38

Wordpress WidgetsWidgets are a cool new feature built into wordpress version 2.2, and allow you to drag mini plugins into your widget-enabled theme’s sidebars.

They have all kinds of uses, searches, polls, you name it.

This article will show you how to create a customisable Recent post widget for yourself.


Step 1 – Creating the file

First create a file called myRecentPosts_widget.php, you can call it what you like really, as long as you know what it is. Open it up in your favorite text/code editor.

Lets start by adding the ‘php’ tag and some information about the author:

1
2
3
4
5
6
7
8
<?php
/*
Plugin Name: My Recent Posts widget
Description: Adds a sidebar widget to display posts from a specified category
Author: Mike Jolley, jolley_small@tesco.net
Version: 1.0
Author URI: http://blue-anvil.com
*/

Done that? Well done, lets move on.

Step 2 – The widget function begin

Next we need to add the widgets functionality. Lets add the start of our function: the init function, which will wrap all our plugin functionality. We will also add a little code to make sure widgets are enabled (and the widget functions exist), to avoid errors:

1
2
3
4
function widget_myRecentPosts_init() {
 
	if ( !function_exists('register_sidebar_widget') )
		return;

Now we can start adding our widgets functionality, the next code creates our function and gets variable values (some of these we will set later).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function widget_myRecentPosts($args) {
 
		// "$args is an array of strings that help widgets to conform to
		// the active theme: before_widget, before_title, after_widget,
		// and after_title are the array keys." - These are set up by the theme
		extract($args);
 
		// These are our own options
		$options = get_option('widget_myRecentPosts');
		$title = $options['title'];  // Title in sidebar for widget
		$show = $options['show'];  // # of Posts we are showing
		$excerpt = $options['ex'];  // Showing the excerpt or not
		$exclude = $options['exclude'];  // Categories to exclude
                      if ($show<1) $show = 1;
		if ($exclude=="") $exclude = "0";

The next piece of code will start outputting to the screen, using the default $args, and our widget title.

1
2
                      // Output
		echo $before_widget . $before_title . $title . $after_title;

Step 3 – The Posts Query

The next code starts pulling results from the database using queries. This is more complex, so don’t worry if it confuses you!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// GET POSTS
			global $wpdb;
			$sql = 'select DISTINCT * from '.$wpdb->posts.'
			INNER JOIN (select * from '.$wpdb->post2cat.'
			INNER JOIN '.$wpdb->categories .' ON '.$wpdb->post2cat.'.category_id = '.$wpdb->categories .'.cat_ID)
			as A ON '.$wpdb->posts.'.ID = A.post_ID
			WHERE (A.cat_ID NOT IN ('.$exclude.'))
			AND '.$wpdb->posts.'.post_status="publish"
			AND '.$wpdb->posts.'.post_type="post"
                        GROUP BY ID
			ORDER BY '.$wpdb->posts.'.post_date
			DESC LIMIT 0,'.$show.';';
 
			$posts = $wpdb->get_results($sql);

The above query gets all posts that are published, not excluded (from one of our options), and orders them by date, limiting the number queried to another of our options.

The next piece of code checks if we had any results, and starts looping to output them in the sidebar.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
			// start list
			echo '<ul>';
				// were there any posts found?
				if (!empty($posts)) {
					// posts were found, loop through them
					 foreach ($posts as $post) {
 
							// format a date for the posts
							$post->post_date = date("F j, Y",strtotime($post->post_date));
 
							// if we want to display an excerpt, get it/generate it if no excerpt found
							if ($ex) {
								 if (empty($post->post_excerpt)) {
									 $post->post_excerpt = explode(" ",strrev(substr(strip_tags($post->post_content), 0, 100)),2);
									 $post->post_excerpt = strrev($post->post_excerpt[1]);
									 $post->post_excerpt.= " [...]";
								 }
							}
 
							//output to screen
							echo '<li>
							<a class="post" rel="bookmark" href="'.get_permalink($post->ID).'"><span class="inner">
							<strong class="title lifestyle">'.$post->post_date.' - '.$post->post_title.'</strong>';
 
							if ($ex) echo '<br />'.strip_tags($post->post_excerpt);
 
							echo '</span></a></li>';
					 }
				} else echo "<li>No recent Posts</li>";
		// end list
		echo '</ul>';

That was a lot, but its commented so read through to get a better understanding of how the rows are outputted. To finish our function we just close the function (and output the closing element of the widget).

1
2
3
// echo widget closing tag
		echo $after_widget;
	}

Step 4 – Creating the settings

Widgets make it easy to create a small settings dialog for your widget, our widget is going to get settings for:

  • Widget title
  • posts to show
  • whether or not to show excerpt
  • Categories to exclude from the list

Lets get started. We declare our settings function, and load the variables.

1
2
3
4
5
6
7
8
	// Settings form
	function widget_myRecentPosts_control() {
 
		// Get options
		$options = get_option('widget_myRecentPosts');
		// options exist? if not set defaults
		if ( !is_array($options) )
			$options = array('title'=>'Recent Posts', 'show'=>'5', 'excerpt'=>'1','exclude'=>'');

Next we check if the settings form has been posted, updating the settings if it has.

1
2
3
4
5
6
7
8
9
10
                      // form posted?
		if ( $_POST['recentArticles-submit'] ) {
 
			// Remember to sanitize and format use input appropriately.
			$options['title'] = strip_tags(stripslashes($_POST['recentArticles-title']));
			$options['show'] = strip_tags(stripslashes($_POST['recentArticles-show']));
			$options['excerpt'] = strip_tags(stripslashes($_POST['recentArticles-excerpt']));
			$options['exclude'] = strip_tags(stripslashes($_POST['recentArticles-exclude']));
			update_option('widget_myRecentPosts', $options);
		}

So we have handled posted options, now we need a form! Lets get the options to show in the form by default.

1
2
3
4
5
		// Get options for form fields to show
		$title = htmlspecialchars($options['title'], ENT_QUOTES);
		$show = htmlspecialchars($options['show'], ENT_QUOTES);
		$excerpt = htmlspecialchars($options['excerpt'], ENT_QUOTES);
		$exclude = htmlspecialchars($options['exclude'], ENT_QUOTES);

Now we can happily display the form. Notice we only need to write the fields, the widgets engine handles the form code!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
		// The form fields
		echo '<p style="text-align:right;">
				<label for="myRecentPosts-title">' . __('Title:') . '
				<input style="width: 200px;" id="myRecentPosts-title" name="myRecentPosts-title" type="text" value="'.$title.'" />
				</label></p>';
		echo '<p style="text-align:right;">
				<label for="myRecentPosts-show">' . __('Show:') . '
				<input style="width: 200px;" id="myRecentPosts-show" name="myRecentPosts-show" type="text" value="'.$show.'" />
				</label></p>';
		echo '<p style="text-align:right;">
				<label for="myRecentPosts-excerpt">' . __('Show excerpt:') . '
				<input style="width: 200px;" id="myRecentPosts-excerpt" name="myRecentPosts-excerpt" type="text" value="'.$excerpt.'" />
				</label></p>';
		echo '<p>Enter the categories to exclude below, this must be a comma separated list of category id\'s!</p>';
		echo '<p style="text-align:right;">
				<label for="myRecentPosts-exclude">' . __('Exclude:') . '
				<input style="width: 200px;" id="myRecentPosts-exclude" name="myRecentPosts-exclude" type="text" value="'.$exclude.'" />
				</label></p>';
		echo '<input type="hidden" id="myRecentPosts-submit" name="myRecentPosts-submit" value="1" />';
	}

And thats that for settings!

Step 5 – Register the widgets

The last piece of code registers the widget for use. After that were done.

1
2
3
4
5
6
7
8
9
10
11
	// Register widget for use
	register_sidebar_widget(array('My Recent Posts', 'widgets'), 'widget_myRecentPosts');
 
	// Register settings for use, 300x100 pixel form
	register_widget_control(array('My Recent Posts', 'widgets'), 'widget_myRecentPosts_control', 300, 200);
}
 
// Run code and init
add_action('widgets_init', 'widget_myRecentPosts_init');
 
?>

Widget armed

Now its finished, upload to plugins directory, activate it, then go to the widgets control panel (under the presentation tab of the wordpress admin) and drag it into one of your sidebar widget sections.

Added widget

Click the little form icon on the widget to bring up the settings form

Settings

In action it looks like this:

In action

Lazy mans corner

For a full code listing, click here

Download it all zipped up below.

Download My Recent posts widget Version 1.1


Enjoy

I hope my little tutorial on widget creation was of a great help :)

Found this post useful? Why not buy me a coffee!

Related Entries

38 Responses to “Create a Wordpress Recent-Posts Widget”

RSS feed for comments on this post.

  1. Anthony Brewitt says:

    Just wanted to add for all those widget newbies that a widget is basically the same as a plugin but is easier to implement via drag and drop etc. You can give yout WP theme Widgets by downloading the Automatic Widget Plugin.

    Comment made on May 17, 2007 at 8:39 am

  2. Will says:

    Nice article. With my sites custom theme would I be able to use widgets by just installing the Automatic Widget Plugin, or would it be more complicated?

    Comment made on May 17, 2007 at 9:16 am

  3. Mike Jolley says:

    Hey Ant, actually you don’t need the plugin with wordpress 2.2., its built in.

    WIll – Either upgrade to 2.2 or install the plugin. Then you just need to add a small chunk of code in the sidebar of your theme, read here http://automattic.com/code/widgets/themes/ e.g:

    1
    2
    
    <?php if ( !function_exists('dynamic_sidebar')
            || !dynamic_sidebar() ) : ?>

    Then you add a new file in your theme called functions.php with something like this inside it:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    <?php
    if ( function_exists('register_sidebar') )
        register_sidebar(array(
            'before_widget' => '',
            'after_widget' => '',
            'before_title' => '<div class="title">',
            'after_title' => '</div>',
        ));
    ?>

    And your good to go!

    Comment made on May 17, 2007 at 9:26 am

  4. Jonathan says:

    Awesome tutorial Mike, thanks for sharing : ).

    -Jonathan

    Comment made on May 17, 2007 at 2:50 pm

  5. Mike Cherim says:

    Nice Mike. Question for you: How are you managing the color codes in your pre boxes? Normally when I want to do that I present code in a *.phps file, but I wouldn’t know how to implement that in something that’s included in a post etc.

    Comment made on May 17, 2007 at 4:12 pm

  6. Mike Jolley says:

    Comment made on May 17, 2007 at 4:28 pm

  7. Mike Cherim says:

    Thanks :)

    Comment made on May 17, 2007 at 5:51 pm

  8. Anthony Brewitt says:

    Your right on that^

    Comment made on May 29, 2007 at 2:48 pm

  9. Nathan Snipes says:

    Great article. I downloaded your file for use on my blog because I wanted the ability to exclude a few categories from the Recent Posts section.

    It seems to work great with one small exception: it lists each post twice!

    Has anyone else had an issue with this? Any one know what might be causing this?

    Comment made on June 24, 2007 at 2:33 am

  10. Nathan Snipes says:

    Upon further investigation the problem seems to be with how many categories a post is filed under.

    For example, if Post1 is filed under Category1 and Category2 it will be listed twice. If Post1 is filed under Category1, Category2 and Category3 it will be listed 3 times, etc.

    I’ve looked through the code but I’m not really sure what I should be looking for. Can someone help?

    Comment made on June 24, 2007 at 3:31 am

  11. Mike Jolley says:

    Ive updated the download and code listings to deal with that issue, thanks.

    Comment made on June 25, 2007 at 10:44 pm

  12. Francesco says:

    Hi
    really nice tutorial and cool widget. I have done some modifications to have the beginning of the excerpt when rolling over the link. I don´t know much php, so I was wondering how can I change the call for the post-date to use the global locale settings (in my case italian) rather than the default english used by php.
    I was looking at using the setlocale variable, but I was unable to get it to work. Any suggestion? Thanks /F

    Comment made on July 16, 2007 at 1:26 pm

  13. Francesco says:

    Nevermind. I got that sorted :) If anyone is interested in the changes i made you can go to http://www.francescoinsvezia.net/?p=364. Thank you Mike!

    Comment made on July 16, 2007 at 2:28 pm

  14. Lair says:

    Thanks for this great tutorial, I coded my first plugin with it : A simple “add to my google page” button with a customizable link :)

    Comment made on July 27, 2007 at 10:39 pm

  15. komakai says:

    I d/l the widget. Uploaded, and activated. error followed:

    WordPress database error: [You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'select * from wp_post2cat INNER JOIN wp_categories ON wp_po]
    select DISTINCT * from wp_posts INNER JOIN (select * from wp_post2cat INNER JOIN wp_categories ON wp_post2cat.category_id = wp_categories.cat_ID) as A ON wp_posts.ID = A.post_ID WHERE (A.cat_ID NOT IN (0)) AND wp_posts.post_status=”publish” AND wp_posts.post_type=”post” GROUP BY ID ORDER BY wp_posts.post_date DESC LIMIT 0,5;

    Comment made on July 29, 2007 at 11:00 pm

  16. Mike Jolley says:

    if your using mysql below v4.1 then it does not support nested selects

    Comment made on July 29, 2007 at 11:09 pm

  17. Luis Olmos says:

    Love the widget, but is there a way to include a picture?
    1. Say all posts with pictures have the image at the beginning of the text. What needs to be done so that it displays the title then the pic (resized by either the script or the css) and then the text?
    I’ve already fiddled around with your code so that it displays only the post title as the link and the text is put in a tag. echo '
    <a>ID).'"&gt;
    <strong>'.$post-&gt;post_title.'</strong></a>';

    if ($excerpt) echo ''.strip_tags($post-&gt;post_excerpt);

    echo '';
    i just cant figured how to do get the pic to load.

    2. if i want 2 instances of the widget displaying a separate category how do I modify the source file? I’ve changed the name of the widget and instances within it, wordpress sees it loads it but on the widget bar i can load it but i have no options.
    Thanks for this great plugin/widget!!!

    Comment made on August 16, 2007 at 1:27 pm

  18. Patrick says:

    Thanks for the widget but how do I exclude the date with only the post title shown?

    Comment made on September 17, 2007 at 10:35 am

  19. Joel Bergqvist says:

    I would also like to use the widget twice at the same time (two intances) How is this done?

    Comment made on September 18, 2007 at 8:27 am

  20. alex says:

    This version is not compatible with WP 2.3 – wp_post2cat no longer exists

    Comment made on September 30, 2007 at 1:49 am

  21. fadi says:

    hi there,

    thank you for this tutorial.
    is it possible to customise this widget using css?how?

    Comment made on October 3, 2007 at 8:51 am

  22. alias says:

    how to plug this code anywhere in the page i don’t like widgets personally is there a ?

    Comment made on October 16, 2007 at 3:14 pm

  23. Alex says:

    Hey Mike,

    since the plugin is not compatible with WP 2.3 are you planning to upgrade the plugin? It would be very sad if it’s not usable in the future :(

    Thanks

    Alex

    Comment made on October 23, 2007 at 4:24 pm

  24. Ellen says:

    I’m interested in adding to this widget an indication of how many comments a post has received… i.e,

    Debugging (Tuesday, Sep 18)
    Why doesn’t everyone just get a Mac? (7 comments)

    but am not sure what code to add to the widget or where to add it.

    Comment made on November 4, 2007 at 6:25 pm

  25. Justin says:

    Thanks for putting together a great plugin, Mike. I made a few changes to suit my own needs, and in the process updated it to work with 2.3.

    @Alex – To make this widget 2.3 ready, you can just replace the wpdb calls with something like:

    global $post;
    $posts = get_posts('numberposts='.$show.'&amp;category=' . $category . '&amp;exclude=' . $exclude);

    Comment made on November 11, 2007 at 7:07 pm

The comments are closed.

About this site

Blue Anvil is the online web design journal & portfolio of , a web designer from Norfolk, England. Read More »
ThemeSlice
  • Featured work - More

    • Beefjack
    • Integrity
    • theotaku.com
  • Latest Tweet - More

    • @skjreilly no problem :)
  • Out of the blue - More

    • Switched: From Shared to VPS

      It’s been about two weeks now since I made the transition from a shared reseller hosting account to a VPS (Virtual Private Server) account – impressions so far, excellent performance but fiddly to configure.

      The reason I wanted to change from shared hosting was the fact the server was always being hacked (even though ALL my scripts were secure), there was frequent downtime, support blamed me for problems every time, and it was slow as hell.

      Those used to a shared hosting environment would probably not know where to start when faced with configuring a VPS. Luckily, a lot of it was pre-configured when I received my account – certainly some of the major security holes were patched. I was not satisfied with those however. As a victim of hacking in the past (previous host swears it was not there fault, something I don’t believe) I took extra care to secure it as a much I could – configuring brute force detection, the firewall, installing mod security (excellent rules for that here: http://www.atomicorp.com/wiki/index.php/Atomic_ModSecurity_Rules) and going though multiple guides (like this one: http://www.webhostingtalk.com/showthread.php?t=468168) with a fine-tooth comb.

      The result? My pages are loading at least 6 times faster, I have had no down time (or at least have not noticed any), and I feel in control and happy. No longer am I at the mercy of shared hosts :)

      If your interested, I chose ServInt as my provider as they offered a great deal, as well as being a managed service (so I’m not on my own if I screw things up). I was tempted by the bells and whistles of Media Temple, but felt the ServInt service was better value.

    • Download Monitor 3.2.2 Maintenance Release

      Download Monitor has received some more love and has been updated. Here’s the change log from the new version:

      • Small bugfix in uploader.php – cat ID
      • Changed stats graph calculation – thanks lggemini
      • Changes to headers in download.php to avoid caching
      • File Browser fixes – $root was clashing with something….
      • exclude_cat works in all sections of download_page now
      • Removed hardcoding of /uploads/
      • Added action to download.php – should be able to use it to stop a download if you want – maybe limiting downloads per day or something? Whatever you want…
      • Made it so if you post new file on ‘edit’ screen, the post date is updated.
      • Fixed the ‘blank meta’ section which blanks out custom field values when nothing is set.
      • Moved ‘allow_url_fopen’ check.
      • Someone said downloads don’t work with spaces in the name. They do! Wasting my time sonny…
      • All work and no play make jolley a dull boy
      • Had to rename capabilities so they work. Apologies if you have to set this up again! Cheers to Mark Dingemanse.
      • {category_ID} custom format tag added. Useful if you want to send someone to its category on the DL page I guess. Also added {category_other} so when no category is set “other” is shown – this is because the download page can show an ‘other’ section if you want it to.
      • You can now manually edit the post date on the edit download screen.

      If you have edited capabilities for download monitor user permissions, you’ll have to again sorry! This is because I named them too long. Also, you should check your forced downloads still work because there was a logic error meaning they may not have been forced after-all…

      Enjoy.

    • Mahousive update to Download Monitor (3.2)

      Today I completed the update for the Wordpress Download Monitor Plugin – many tweaks, fixes, and features added. There were no changes to the database structure so people upgrading should be fine. Here is the list from the change log:

      • {user} tag added for custom formats
      • ‘autop’ option fix
      • Download page buttons applied with CSS so they are easier to customise/translate.
      • Fix for pagination bug after editing a download
      • Category output fix on edit downloads screen
      • Category urls on download page use ID rather than name to prevent errors when cats have the same names.
      • exclude_cat added to download_page shortcode
      • Localised ‘hits’ ‘date’ ‘title’ on download page
      • Option to disable the download logging
      • Read file ‘chunked’ some people found large files were corrupted so this should help (fingers crossed)
      • Added show_tags option to download page – displays x amount of tags on the download page.
      • File Browser root setting and download.php logic/mime types modified thanks to Jim Isaacs (jidd.jimisaacs.com)
      • Interface Improvements
      • Bulk edit categories, custom fields, tags, member only downloads
      • Added roles for download monitor admin – should be able to use with a role manager plugin if you want anyone other than admin to access the admin section e.g. http://wordpress.org/extend/plugins/capsman/
      • Change redirect after add
      • Edit Cat names/parents
      • Dedicated tags and thumbnails fields (they still use meta table though)

      And yes, those category link bugs are fixed at long last, and you can edit category names finally. Phew!

    • Wordpress Spam Stopper Plugin Updated

      Spam stopper has been updated to v3.1 – and most of it has been recoded. Here’s the full list of changes:

      • Added changelog to readme.
      • Email validation bug squashed
      • Cached comments now work; if user forgets to fill in antispam or makes a mistake (and the JS does not catch it) the users comment will not be lost.
      • Redone entire code to make it more efficient
      • Admin section added for changing the antispam question
      • Form ID and honeypot trap added to form
      • Fully localized

      You can get the plugin from wordpress.org: http://wordpress.org/extend/plugins/spam-stopper/

      For support, please keep my comments clean and post on either the wordpress forums or my forum.

      To help support spam-stopper you can make a donation (buy me a coffee, or several) or rate it on wordpress.org. Thanks!