Video icon 64
Learning to code? Skill up faster with our practical video courses. Start your free trial today.
Advertisement

Building a Recent Post Widget Powered by SimplePie

by

In this tutorial, I will introduce SimplePie, build a widget plugin that displays recently published articles queried from the WordPress feed using SimplePie, and discuss the performance advantage of querying posts from the WordPress feed instead of the database.

Introduction to SimplePie

SimplePie is a free, very fast and easy-to-use feed parser, written in PHP that handles all of the dirty work when it comes to fetching, caching, parsing, normalizing data structures between formats, handling character encoding translation, and sanitizing the resulting data.

Getting Started With SimplePie

To install and get started using SimplePie, check out the following steps:

  1. Download SimplePie library and create two folders: php and cache.
  2. Upload library/ and autoloader.php to the php folder you just created.
  3. SimplePie is now installed and ready to be use.

Let's see how to use SimplePie to retrieve content found in a feed.

<?php
// Make sure SimplePie is included. You may need to change this to match
// the location of autoloader.php

require_once ('../autoloader.php');

// instantiate the SimplePie class
$feed = new SimplePie();

// Set the feed to process.
$feed->set_feed_url( 'http://feeds.fedburner.com/tech4sky' );

// Run SimplePie.
$feed->init();

// Send content to the browser as text/html and the UTF-8 character set.
$feed->handle_content_type();
?>
<!DOCTYPE html>
<head>
	<title>Sample SimplePie Page</title>
</head>
<body>

<div class="header">
  <h1><a href="<?php echo $feed->get_permalink(); ?>"><?php echo $feed->get_title(); ?></a></h1>
  <p><?php echo $feed->get_description(); ?></p>
</div>

<?php
// Here, we'll loop through all of the items in the feed, and $item represents the current item in the loop.
foreach ( $feed->get_items() as $item ):
?>

  <div class="item">
    <h2><a href="<?php echo $item->get_permalink(); ?>"><?php echo $item->get_title(); ?></a></h2>
    <p><?php echo $item->get_description(); ?></p>
    <p><small>Posted on <?php echo $item->get_date('j F Y | g:i a'); ?></small></p>
  </div><!-- .item -->

<?php endforeach; ?>

SimplePie is easy to install and use, isn't it?

In the next section, we will be building a widget that display recently publish articles retrieved from WordPress feed.

Performance Advantage of Querying Post From Feed Over Database

Many of us use a widget to display Recent Posts on the sidebar of our WordPress blog. Many of these plugins query the database to retrieve the recently published articles.

Considering the fact that database-driven web application like WordPress take time querying and writing to the database, it's fair to say that the fewer the number of database queries, the more the greater improvement we can see on our page load time.

Rather than querying the database, we could retrieve the recently published articles from our WordPress feed using SimplePie which can significantly improve performance.

SimplePie has several options for caching feed data built-in so you don’t have to pull the entire feed every time.

One of such is the file-based caching system that store cache feed item in a server-writable directory which further maximize performance.

Building a Recent Post Widget With SimplePie

Building a Widget in WordPress is easy and straight-forward.

First, extend the WP_Widget class, include these four methods: __construct(), widget(), form(), update() in the class and finally register the widget.

Recent Post Widget powered by SimplePie
  1. Create a class extending the WP_Widget
    class Tutsplus_simplepie extends WP_Widget {}
  2. Give the widget a name and description via the __construct() magic method
    function __construct() {
    	parent::__construct(
    		'tutsplus_widget', // Base ID
    		__('Recent Post powered by SimplePie', 'text_domain'), // Name
    		array( 'description' => __( 'Most recent posts generated from WordPress feed using SimplePie', 'text_domain' ), )
    	);
    }
  3. The widget() method displays the front-end of the widget.
    public function widget( $args, $instance ) {
    
    	$feedURL = empty( $instance['feedURL'] ) ? site_url() . '/feed' : $instance['feedURL'];
        $feedNumber = empty( $instance['feedNumber'] ) ? 5 : $instance['feedNumber'];
    	$showDate = empty( $instance['showDate'] ) ? 0 : 1;
        $showDescription = empty( $instance['showDescription'] ) ? 0 : 1;
    
    	echo $args['before_widget'];
    
    	$title = apply_filters( 'widget_title', $instance['title'] );
    	if ( ! empty( $title ) ) {
    		echo $args['before_title'] . $title . $args['after_title'];</pre>
    </li>
    <li>
        <pre>require_once 'php/autoloader.php';
    
        // Instantiate and process this feed with all of the default options.
        $feed = new SimplePie();
    
        // Set which feed to process.
        $feed->set_feed_url( $feedURL );
    
        // Set where the cache files should be stored
        $feed->set_cache_location( plugin_dir_path( __FILE__ ) . 'cache' );
    
        // Run SimplePie.
        $feed->init();
    
        // ensure that the content is sent to the browser as text/html and the UTF-8 character set
        $feed->handle_content_type();
    
        // Figure out how many total items there are, but limit it to 5.
        $maxitems = $feed->get_item_quantity( $feedNumber );
    
        // Build an array of all the items, starting with element 0 (first element).
        $rss_items = $feed->get_items( 0, $maxitems );
    
    ?>
    
    <ul>
    	<?php if ( $maxitems == 0 ) : ?>
    	<li>
    		<?php echo "No item found"; ?></li>
    	<?php else : ?>
    		<?php // Loop through each feed item and display each item as a hyperlink. ?>
    		<?php foreach ( $rss_items as $item ) : ?>
    	        <li>
    		        <a href="<?php echo esc_url($item -> get_permalink()); ?>" title="<?php echo esc_html( $item -> get_title() ); ?>">
                        <?php echo esc_html( $item -> get_title() ); ?>
                    </a>
    		        <?php if ( $showDate ) { echo "<span class='date'>" . $item -> get_date('F j Y') . "</span>"; } ?>
    		        <?php if ( $showDescription ) { echo "<div class='description'>" . $item -> get_description() . "</div>"; } ?>
    	        </li>
    	    <?php endforeach; ?>
    	<?php endif; ?>
    </ul>
    
    <?php echo $args['after_widget'];
    }
  4. Create the widget settings form with the form() method
    public function form( $instance ) {
    
    	$defaults = array('title' => 'Recent Posts',
    	    'feedURL' => get_site_url() .'/feed',
    	    'feedNumber' => 5
    	);
    	$instance = wp_parse_args( (array)$instance, $defaults );
    	$title = $instance['title'];
    	$feedURL = $instance['feedURL'];
    	$feedNumber = $instance['feedNumber'];
    	$showDate = $instance['showDate'];
    	$showDescription = $instance['showDescription'];
    ?>
    <p>
    	<label for="<?php echo $this->get_field_id('title'); ?>">Title:</label>
    	<input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>">
    </p>
    <p>
        <label for="<?php echo $this->get_field_id('feedURL'); ?>">Feed:</label>
        <input class="widefat" id="<?php echo $this->get_field_id('feedURL'); ?>" name="<?php echo $thi->get_field_name( 'feedURL' ); ?>" type="text" value="<?php echo esc_attr( $feedURL ); ?>">
    </p>
    <p>
        <label for="<?php echo $this->get_field_id( 'feedNumber' ); ?>">Number of posts to show:</label>
        <input id="<?php echo $this->get_field_id( 'feedNumber' ); ?>" name="<?php echo $this->get_field_name( 'feedNumber' ); ?>" size="3" type="text" value="<?php echo esc_attr( $feedNumber ); ?>">
    </p>
    <p>
        <label for="<?php echo $this->get_field_id( 'showDate' ); ?>">Show Date?:</label>
        <input name="<?php echo $this->get_field_name( 'showDate' ); ?>" value="1" type="checkbox" <?php checked( $showDate, 1 ); ?>">
    </p>
    <p>
        <label for="<?php echo $this->get_field_id('showDescription'); ?>">Show Summary?:</label>
        <input name="<?php echo $this->get_field_name('showDescription'); ?>" value="1" type="checkbox" <?php checked( $showDescription, 1 ); ?>">
    </p>
    <?php
    }
  5. Finally the update() method sanitizes and saved the widget settings to the database.
    public function update( $new_instance, $old_instance ) {
        
        $instance = array();
        $instance['title'] = ( ! empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : '';
        $instance['feedURL'] = ( ! empty( $new_instance['feedURL'] ) ) ? strip_tags( $new_instance['feedURL'] ) : '';
        $instance['feedNumber'] = ( ! empty( $new_instance['feedNumber'] ) ) ? strip_tags( $new_instance['feedNumber'] ) : '';
        $instance['showDate'] = ( ! empty( $new_instance['showDate'] ) ) ? strip_tags( $new_instance['showDate'] ) : '';
        $instance['showDescription'] = ( ! empty( $new_instance['showDescription'] ) ) ? strip_tags( $new_instance['showDescription'] ) : '';
    
        return $instance;
        
    }

The WordPress fetch feed function also retrieves feed and parses it using SimplePie. If you wish to use the fetch feed function instead of implementing SimplePie from ground up, change the widget() method inside the Tutsplus_simplepie Widget class to the code below.

public function widget( $args, $instance ) {

  $feedURL = empty( $instance['feedURL'] ) ? site_url().'/feed' : $instance['feedURL'];
  $feedNumber = (int) empty( $instance['feedNumber'] ) ? 5 : $instance['feedNumber'];
  $showDate = empty( $instance['showDate'] ) ? 0 : 1;
  $showDescription = empty( $instance['showDescription'] ) ? 0 : 1;

  echo $args['before_widget'];

    $title = apply_filters( 'widget_title', $instance['title'] );
    if ( ! empty( $title ) )
        echo $args['before_title'] . $title . $args['after_title'];

    include_once( ABSPATH . WPINC . '/feed.php' );

    // Get a SimplePie feed object from the specified feed source.
    $rss = fetch_feed( $feedURL );

    if ( ! is_wp_error( $rss ) ) : // Checks that the object is created correctly

        // Figure out how many total items there are, but limit it to 5.
        $maxitems = $rss->get_item_quantity( $feedNumber );

        // Build an array of all the items, starting with element 0 (first element).
        $rss_items = $rss->get_items( 0, $maxitems );

    endif;
?>

<ul>
 <?php if ( $maxitems == 0 ) : ?>
    <li><?php echo "No item found"; ?></li>
 <?php else : ?>
    <?php // Loop through each feed item and display each item as a hyperlink. ?>
    <?php foreach ( $rss_items as $item ) : ?>
        <li>
            <a href="<?php echo esc_url($item -> get_permalink()); ?>" title="<?php echo esc_html($item->get_title()); ?>">
                <?php echo esc_html($item->get_title()); ?>
            </a>
            <?php if ($showDate) { echo "<span class='date'>" . $item->get_date('F j Y') . "</span>"; } ?>
            <?php if ($showDescription) { echo "<div class='description'>" . $item->get_description() . "</div>"; } ?>
        </li>
    <?php endforeach; ?>
  <?php endif; ?>
</ul>

<?php echo $args['after_widget'];
}
?>

Note on the Widget

The appearance of the widget will vary from theme to theme based on your stylesheet. Some of us host our feed on FeedBurner so I added a feed URI option field in the widget settings form incase you want to change it with the default feed set to http://yoursite.com/feed.

Other widget options include altering the number "Recent Post" to display , show / hide post summary and date for each post.

Recent Post widget setings form

Conclusion

We are done building the recent post widget. To further understand how the widget was built and how to implement it on your WordPress site, download the tutorial file.

When extracted, the file contains two plugin files in zip:

  1. The first is the widget built using SimplePie.
  2. The other built using WordPress fetch feed function which coincidentally also uses the SimplePie library.

Hopefully this helps with working with building widgets and SimplePie in the future. 

Let me know your thoughts in the comments!

Advertisement