Creating a “Most-Commented-on Posts” Plugin for WordPress
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 thewidgets_init
action. - The
widget
function of ourMost_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 withorderby
,order
andposts_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 theWP_Post
objects. - We’re then displaying the title and the number of comments.
This is how our widget looks at present:
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:
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.