Creating a “Most-Commented-on Posts” Plugin for WordPress

Share this article

Fresh content on any site is a good thing. A nice touch is to display your most discussed posts to your website visitors. In the case of WordPress, a widget is the ideal place for this. Users who wouldn’t otherwise know where to go after reading the current post, might check out and hopefully participate in your blog’s most commented posts. Your most commented on posts are commonly also the ones which bring most page views and are the most interesting.

In this tutorial we will create a basic plugin to display most commented on posts in a widget. Although there are lots of plugins available for this purpose, many of them tend to be overwhelming and also don’t support caching. In this article, the plugin we’ll build will be lightweight and will cache the top 10 commented posts for 24 hours.

Plugin Directory and Files

To start with the plugin development, create a directory called most-commented-widget and create the following files in it:

--most-commented-widget
  -most-commented-widget.php
  -style.css

In the most-commented-widget.php file, add the following text to make the plugin installable.

<?php

/*
Plugin Name: Most Commented Posts Widget
Plugin URI: https://www.sitepoint.com
Description: Displays most commented posts in an widget
Author: Narayan Prusty
*/

The get_posts() Function

We will use the get_posts() function instead of the WP_Query object to retrieve the most commented on posts, because using WP_Query directly alters the main loop (i.e., global $wp_query variable) which would cause site issues.

The get_posts() function is used to retrieve an array of WP_Post objects based on a set of parameters. get_posts() internally uses WP_Query object’s query function to construct a MySQL query and execute it. WP_Query object’s query doesn’t alter the main loop.

The Transients API

The Transients API is used to store key value pairs of data, just like the Options API, but with an expiration time. The Transients API stores the data only in cache if persistence caching is configured. Therefore the Transients API is great for caching data.

We will use the Transients API to cache our most commented posts for 24 hours.

Creating a Widget

OK, let’s create our widget. A widget is a class which extends the WP_Widget class. Here’s the code:

class Most_Commented_Post_Widget extends WP_Widget 
{
    public function __construct() 
    {
        parent::__construct("Most_Commented_Post_Widget", "Display Most Commented Posts", array("description" => __("This plugin displays three most commented posts in an widget")));
    }
         
    public function form($instance) 
    {
        if($instance) 
        {
            $title = esc_attr($instance['title']);
        } 
        else
        {
            $title = '';
        }
        ?>
 
        <p>
            <label for="<?php echo $this->get_field_id('title'); ?>"><?php echo "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 $title; ?>" />
        </p>
 
        <?php
    }
         
    public function update($new_instance, $old_instance) 
    {
        $instance = $old_instance;
        $instance['title'] = strip_tags($new_instance['title']);
        return $instance;
    }
         
    public function widget($args, $instance) 
    {
        extract($args);
        
        $title = apply_filters('widget_title', $instance['title']);
        
        echo $before_widget;

        if($title) 
        {
            echo $before_title . $title . $after_title ;
        }

        echo $after_widget;
    }
}

function register_most_commented_widget() 
{
  register_widget("Most_Commented_Post_Widget");
}

add_action("widgets_init", "register_most_commented_widget");

Here’s how the code works:

  • We are registering the widget class using the register_widget function which is called inside the widgets_init action.
  • The widget function of our Most_Commented_Post_Widget class is responsible for echoing the front end output.
  • At present, we’re just displaying the title on the front end.

Retrieving and Displaying the Most Commented On Posts

Here is the implementation of the widget function of the Most_Commented_Post_Widget class which displays the top 10 most commented on posts:

public function widget($args, $instance) 
{
    extract($args);
    
    $title = apply_filters('widget_title', $instance['title']);
    
    echo $before_widget;

    if($title) 
    {
        echo $before_title . $title . $after_title ;
    }

    $posts = null;

    $posts = get_posts(array(
    	'orderby'	=> 'comment_count',
    	'order'     => 'DESC',
    	'posts_per_page' => 10
	));

	?><ul class="most-commented-post-widget"><?php

        foreach ($posts as $key => $value) 
        {
        	$title = $value->post_title;
        	$comment_count = $value->comment_count;
        	$url = get_permalink($value->ID);

        	?>
        	<li>
        		<a href="<?php echo $url; ?>"><?php echo $title; ?></a>
        		<br>
        		<small><?php echo $comment_count; ?> comments</small>
        	</li>
        	<?php

        }

    ?></ul><?php
    echo $after_widget;
}

Here is how the code works:

  • We’re calling the get_posts function with orderby, order and posts_per_page array keys. We are retrieving the top 10 most commented on posts in descending order.
  • And then we’re using a foreach construct to loop through the array of the WP_Post objects.
  • We’re then displaying the title and the number of comments.

This is how our widget looks at present:

WordPress Comment Widget 1

But we haven’t started caching the result, yet. Let’s see how to cache the get_posts() result.

Caching the Most Commented On Posts List

Let’s see how we can implement the Transients API in our widget. Here’s the code of the widget function with the Transients API implementation:

public function widget($args, $instance) 
{
    extract($args);
    
    $title = apply_filters('widget_title', $instance['title']);
    
    echo $before_widget;

    if($title) 
    {
        echo $before_title . $title . $after_title ;
    }

    $posts = null;

    if(get_transient("most_commented_posts") == false)
    {
    	$posts = get_posts(array(
	    	'orderby'	=> 'comment_count',
	    	'order'     => 'DESC',
	    	'posts_per_page' => 10
		));

    	set_transient("most_commented_posts", json_encode($posts), 86400);
    }
    else
    {
    	$posts = get_transient("most_commented_posts");
    	$posts = json_decode($posts);
    }

	?><ul class="most-commented-post-widget"><?php

        foreach ($posts as $key => $value) 
        {
        	$title = $value->post_title;
        	$comment_count = $value->comment_count;
        	$url = get_permalink($value->ID);

        	?>
        	<li>
        		<a href="<?php echo $url; ?>"><?php echo $title; ?></a>
        		<br>
        		<small><?php echo $comment_count; ?> comments</small>
        	</li>
        	<?php

        }

    ?></ul><?php
    echo $after_widget;
}

Here, we’re storing the resultant array as a transient with a expiration timer for 24 hours. If the transient returns false, then we’re running the query again and storing the result as a transient for next 24 hours. Now the plugin will play much nicer with MySQL.

Styling the Widget

Let’s style our widget to look more professional. Put this code in the plugin file to enqueue the style.css file.

function most_commented_widget_style() 
{
    wp_register_style("most-commented-post-widget-style", plugin_dir_url(__FILE__) . "style.css");
    wp_enqueue_style("most-commented-post-widget-style");
}

add_action("wp_enqueue_scripts", "most_commented_widget_style");

Place this code in the style.css file to style the lists and add some margin.

.most-commented-post-widget
{
	list-style: none;
}

.most-commented-post-widget li
{
	margin-bottom: 20px;
}

This is what our widget should now look like:

WordPress Comment Widget Finished

Conclusion

In this article I’ve shown you how to easily build your own Most Commented On Posts plugin for WordPress. You can now go ahead and expand on this to display images and add more information. Please share your experience with your own plugins below.

Narayan PrustyNarayan Prusty
View Author

Narayan is a web astronaut. He is the founder of QNimate. He loves teaching. He loves to share ideas. When not coding he enjoys playing football. You will often find him at QScutter classes.

ChrisBpluginwidgetwidgetsWordPresswordpress development
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week