Hello there. I am Terry and I am a full-time undergraduate based in Singapore. I take photos, write a blog and design websites.

And no, I'm not a teddy bear.

WP Widget: Load posts in a category

As I was tinkering with Theme Hybrid lately to prepare myself for major design jobs up ahead, I felt that I should no longer try to hardcode anything into the hybrid sidebar. I have to admit that it is indeed lucrative to simply put a copy of sidebar-primary.php in the child theme folder – identifical files will force Hybrid to load the file from child theme folder instead. Afterall, one will simply have to copy the file, remove the dynamic sidebar codes and replace with your own hardcoded sidebar elements.

Justin Tadlock, the creator and developer behind the Hybrid framework (of which the current WP theme is built on), has written a meticulous and beautiful tutorial on how to create a widget from scratch for WP2.8 and above. His tutorial is straight-forward and simple – more importantly, he provided a sample widget code that you can download at the end of the day and tinker with it on your own site.

There are two ways to introduce widgets into your WordPress installation:

  1. Through a plugin file, which you place in your /[blog-root]/wp-content/plugins/ folder, or
  2. Through your theme’s own functions.php file located in /[blog-root]/wp-content/themes/[theme-folder]/. If the file is not present, you can create it yourself but most probably the theme does not support widget and further tweaking of sidebar.php is needed (Jeff Starr explains it all in his tutorial).

I will not be covering how to write a widget in this article – I recommend you to read Justin’s tutorial if you need to understand any part of the code I’m posting below. Since I’m working on Theme Hybrid, which has a handful of widget-ready areas, I will no longer have to go through the process of making my child theme widget friendly.

The Widget – Loading Posts in a Category

I don’t have an official name for the widget – and I don’t have any intention to. There are too many plugins out there who offer a similar, or perhaps improved, functionality. What I’m presenting is a piece of code that you can simply put in your theme’s functions.php file without even needing to install a plugin or whatsoever.

Of course, if you want to hardcode it, it’s rather simple:

<?php $recent = new WP_Query("cat=[category_ID]&showposts=[integer]"); while($recent->have_posts()) : $recent->the_post();?>
<ul>
	<li><a href="<?php the_permalink() ?>" <?php the_title(); ?></a></li>
</ul>

Why do it the hard way?, you may ask. It’s simple – you don’t have to modify anything in your theme file in the future. Action and filter hooks have a special place in WordPress, which allows us to construct child themes from frameworks without needing to touch any of the core files at all – except for a single functions.php file in your child theme’s folder. When the framework is upgraded to a new version, one no longer needs to worry about porting the changes over to the new version, or go through the same mind-wrecking cycle of comparing new and old codes.

What the widget does is actually simple – to load posts from a specific category. You will enter the category ID and let the plugin do the crunching. Of course, more customization options are offered too. Just in case you’re curious, this is how the widget looks like in WP2.9:

WP Widget: Load posts in a category

WP Widget: Load posts in a category

The Code

Simply place the codes below sequentially into your theme’s functions.php file. After that, navigate to the widget page from your WP dashboard and you should see a new widget named “List Post in a Specific Category”. I think I heard a silent scream over the naming of the widget, but that’s the best the inner linguist in me can go. Go ahead and give it a new name if you feel like it.

Most of the code is modeled after Justin’s very helpful, heavily annotated example widget code. I have removed some of the comments (that’s why it’s better that you read his tutorial beforehand) for simplicity’s sake. The overall structure remains the same, except for the core functionality of the widget itself.

Add action hook

The first thing we need to do is to register the widget to a function, and then hook the function up with widgets_init.

// Load Custom Theme Widgets
function custom_widgets() {
	register_widget('posts_in_category');
}
add_action('widgets_init', 'custom_widgets');

Declaring a new widget

After adding the action hook, we will need to declare the new widget. We go through a few mandatory lines that describes the widget and assigns it a unique identifier. If you are intending to replace any of the variables, make sure to replicate the changes downstream as well – simply use the “Search and replace all” tool (or any equivalent) that will help you make global changes to the identifiers.

class posts_in_category extends WP_Widget {
 
	// Custom Theme Widget: Display posts from a specific category
	function posts_in_category() {
		$widget_ops = array( 'classname' => 'posts-in-category', 'description' => __('A widget that displays posts from a specific category', 'posts-in-category') );
		$control_ops = array( 'width' => 300, 'height' => 350, 'id_base' => 'posts-in-category-widget' );
		$this->WP_Widget( 'posts-in-category-widget', __('List Posts in a Specific Category', 'posts-in-category'), $widget_ops, $control_ops );
	}

Determine what will the widget display on screen

Of course, when your widget is activated, you would want to present saved data (if input from the user is allowed) in the widgetized area. We will declare 5 different variables, namely:

  1. $title – The title of the widget that will appear in the widgetized area, usually wrapped between header tags.
  2. $category_id – The ID of the category where posts will be fetched from.
  3. $post_count_limit – The maximum number of posts to be queried from the database and be displayed.
  4. $post_orderby – How do you want to arrange the posts in the list? By author, title, date, modified and etc. You will be given the option to choose.
  5. $post_offset – How many posts to skip/pass before displaying the first post.

For more information about the query_posts() function, you can refer to the WordPress codex.

To fetch the code, we will use the template tag get_posts() (how to use it?) to help to fetch posts from a specific category.

Don’t forget to wrap the displayed content between echo $before_widget; and echo $after_widget; – we do not define what wraps around the widget, because that is usually pre-determined by the theme in use already.

	// Displaying widget on screen
	function widget($args, $instance) {
		extract($args);
		$title = apply_filters('widget_title', $instance['title'] );
		$category_id = $instance['category_id'];
		$post_count_limit = $instance['post_count_limit'];
		$post_orderby = $instance['post_orderby'];
		$post_offset = $instance['post_offset'];
		echo $before_widget;
		if ($title) {
			echo $before_title . $title . $after_title;
		}
		$category_posts = get_posts('category=' . $category_id . '&numberposts=' . $post_count_limit . '&orderby=' . $post_orderby . '&offset= ' . $post_offset . '');
		if ($category_posts) {
			$category_posts_result .= '<ul>';
			foreach($category_posts as $post) {
				$category_posts_result .= '<li><a href="' . get_permalink($post->ID) . '">' . $post->post_title . '</a></li>';
			}
			$category_posts_result .= '</ul>';
		}
		else {
			$category_posts_result .= "No posts found in this category";
		}
		echo $category_posts_result;
		echo $after_widget;
	}

Updating widget settings

We cannot forget that we’re allowing users to input the category IDs and other parameters in the widget from the dashboard. However, in order to allow changes to be made to the variables, we will have to allow them to update the widget parameters.

The strip_tags() function is used to remove any tags – we only want texts to be entered, not tags. The reason why post_orderby doesn’t need to be passed through the strip_tags() function is simply because it obtains its values from a dropdown list, which does not contain any tags at the first place.

	// Update widget settings
	function update($new_instance, $old_instance) {
		$instance = $old_instance;
		$instance['title'] = strip_tags($new_instance['title']);
		$instance['category_id'] = strip_tags($new_instance['category_id']);
		$instance['post_count_limit'] = strip_tags($new_instance['post_count_limit']);
		$instance['post_offset'] = strip_tags($new_instance['post_offset']);
		$instance['post_orderby'] = $new_instance['post_orderby'];
		return $instance;
	}

User input interface

In order for a user to enter specific parameters, we have to set up a user interface. The following piece of code simply sets up the input fields for the user – a few text inputs and a dropdown list.

	// Widget setting controls
	function form($instance) {
		$defaults = array('title' => __('Category Name', 'posts-in-category'), 'category_id' => __('1', 'posts-in-category'), 'post_count_limit' => __('5', 'posts-in-category'), 'post_orderby' => 'date', 'post_offset' => __('0', 'posts-in-category'));
		$instance = wp_parse_args((array) $instance, $defaults); ?>
		<p>
			<label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e('Title:', 'posts-in-category'); ?></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%;" />
		</p>
		<p>
			<label for="<?php echo $this->get_field_id('category_id'); ?>"><?php _e('Category ID:', 'posts-in-category'); ?></label>
			<input id="<?php echo $this->get_field_id('category_id'); ?>" name="<?php echo $this->get_field_name('category_id'); ?>" value="<?php echo $instance['category_id']; ?>" style="width: 100%;" />
		</p>
		<p>
			<label for="<?php echo $this->get_field_id('post_count_limit'); ?>"><?php _e('Post Count Limit:', 'posts-in-category'); ?></label>
			<input id="<?php echo $this->get_field_id('post_count_limit'); ?>" name="<?php echo $this->get_field_name('post_count_limit'); ?>" value="<?php echo $instance['post_count_limit']; ?>" style="width: 100%;" />
		</p>
		<p>
			<label for="<?php echo $this->get_field_id('post_offset'); ?>"><?php _e('Offset:', 'posts-in-category'); ?></label>
			<input id="<?php echo $this->get_field_id('post_offset'); ?>" name="<?php echo $this->get_field_name('post_offset'); ?>" value="<?php echo $instance['post_offset']; ?>" style="width: 100%;" />
		</p>
		<p>
			<label for="<?php echo $this->get_field_id('post_orderby'); ?>"><?php _e('Order Posts By:', 'posts-in-category'); ?></label>
			<select id="<?php echo $this->get_field_id('post_orderby'); ?>" name="<?php echo $this->get_field_name('post_orderby'); ?>" class="widefat" style="width:100%;">
				<option <?php if ( 'author' == $instance['format'] ) echo 'selected="selected"'; ?>>author</option>
				<option <?php if ( 'date' == $instance['format'] ) echo 'selected="selected"'; ?>>date</option>
				<option <?php if ( 'title' == $instance['format'] ) echo 'selected="selected"'; ?>>title</option>
				<option <?php if ( 'modified' == $instance['format'] ) echo 'selected="selected"'; ?>>modified</option>
				<option <?php if ( 'parent' == $instance['format'] ) echo 'selected="selected"'; ?>>parent</option>
				<option <?php if ( 'ID' == $instance['format'] ) echo 'selected="selected"'; ?>>ID</option>
				<option <?php if ( 'rand' == $instance['format'] ) echo 'selected="selected"'; ?>>rand</option>
			</select>
		</p>
 
	<?php
	}
}

The final code

I have also uploaded a copy of the entire piece of code. Simply download it, copy it in its entirety and paste in anywhere in your theme’s function.php file – okay, not really anywhere, but do stay within the <?php > tags that are found on the first and last line in the file.

[download id=”11″ format=”2″]

Last

If you have any problems regarding the widget, or any suggested improvements, feel free to reach me through the comments or the contact page. Thank you!

Be Sociable, Share!

Burn after reading » Now you're done reading. What's next?

Related

Related posts that might interest you:

Popular

Posts that are popular among visitors: