Advertisement
Theme Development

How to Create a Simple Post Rating System With WordPress and jQuery

by

There already are many post rating system plugins out there. Surprisingly, no one fits my needs, they either are too complicated or with too many built-in options. So, in this tutorial, you'll learn how to build your own simple post rating functionality, directly within your theme files. There's no need for plugin!


Step 1 Introduction

Post ratings are a good way to get feedback on what your readers really focus on. While I was searching for a simple yet efficient plugin, I realized they all come with too many options and aren't customizable enough. That was my first issue. My second issue was that using too many plugins will slow WordPress down.

So I decided to share with you a way to build your custom post ratings system. We'll use:

  • simple HTML markup and CSS3 so it's easy to customize
  • jQuery to deal with Ajax calls
  • PHP and hooks to handle data

Step 2 HTML Markup

We are going to display a heart-shaped button in the footer section of an article. To do so, we'll add markup in the content-single.php file (within the Twenty Eleven theme).

<p class="post-like">
	<a data-post_id="POST_ID" href="#">
		<span class="qtip like" title="I like this article"></span>
	</a>
	<span class="count">POST_LIKES_COUNT</span>
</p>

Note that we use HTML5 custom meta attributes to store our data so it's really easy to handle with jQuery. Then, this will be generated by PHP, as we'll see in a next step.


Step 3 CSS3

We'll use CSS3 animations to add some visual interactivity and CSS sprites to reduce the number of external images.

article footer  .post-like{
	margin-top:1em
}

article footer .like{
	background:url(images/icons.png) no-repeat;
	width: 15px;
	height: 16px;
	display: block;
	float:left;
	margin-right: 4px;
	-moz-transition: all 0.2s ease-out 0.1s;
	-webkit-transition: all 0.2s ease-out 0.1s;
	-o-transition: all 0.2s ease-out 0.1s
}

article footer .post-like a:hover .like{
	background-position:-16px 0;
}

article footer .voted .like, article footer .post-like.alreadyvoted{
	background-position:-32px 0;
}

At this point, it should looks like this

Post Rating

Step 4 jQuery

We'll use built-in jQuery to handle the ajax requests. On click, jQuery will pass some parameters to our php handler and handle the response to display suitable information.

So let's create a new file called post-like.js and add it to the js folder. Then open it and add this code:

jQuery(document).ready(function() {

	jQuery(".post-like a").click(function(){
	
		heart = jQuery(this);
	
		// Retrieve post ID from data attribute
		post_id = heart.data("post_id");
		
		// Ajax call
		jQuery.ajax({
			type: "post",
			url: ajax_var.url,
			data: "action=post-like&nonce="+ajax_var.nonce+"&post_like=&post_id="+post_id,
			success: function(count){
				// If vote successful
				if(count != "already")
				{
					heart.addClass("voted");
					heart.siblings(".count").text(count);
				}
			}
		});
		
		return false;
	})
})

Explanations

First, let's retrieve the post ID with jQuery's data method and then pass it to our PHP handler. The ajax_var variable is created dynamically with PHP (we'll cover this in the next section).

The best way to use ajax within WordPress is to make calls to admin-ajax.php. It is located in the wp-admin folder and you can bind your callback functions with hooks. Let's see how it works.


Step 5 PHP and Hooks

How are we going to proceed? We are going to bind some functions to WordPress hooks and then enqueue our script and add some PHP-generated JavaScript variables to be used by jQuery.

Hooks

Let's open the functions.php file and get started adding our functions.

First things first, we need to bind functions to WordPress hooks. So add these two lines in your file:

add_action('wp_ajax_nopriv_post-like', 'post_like');
add_action('wp_ajax_post-like', 'post_like');

The first hook is fired when a user is logged in and the other when they are not. See more information about how to implement ajax the right way here: 5 tips for using ajax in WordPress.

You can see the "post-like" part of the hook, which is the action parameter we used in the previous step with jQuery.

Now we'll enqueue our script and declare our variables:

wp_enqueue_script('like_post', get_template_directory_uri().'/js/post-like.js', array('jquery'), '1.0', true );
wp_localize_script('like_post', 'ajax_var', array(
	'url' => admin_url('admin-ajax.php'),
	'nonce' => wp_create_nonce('ajax-nonce')
));

Here, we define two important parameters:

  • url: the complete URI to admin-ajax.php location
  • nonce: a security hash to prevent attacks and mistakes

You can use those parameters with jQuery this way: ajax_var.url and ajax_var.nonce.

"Using WordPress hooks and admin-ajax.php is the safer way to deal with Ajax."

Functions

Let's add the post_like function. It will:

  • Check nonce
  • Retrieve post ID, user's IP and custom post metas
  • Check if the user has already voted or not
  • Save data (IP + votes count) for the current post
  • Return the count value to jQuery
function post_like()
{
	// Check for nonce security
	$nonce = $_POST['nonce'];
 
    if ( ! wp_verify_nonce( $nonce, 'ajax-nonce' ) )
        die ( 'Busted!');
	
	if(isset($_POST['post_like']))
	{
		// Retrieve user IP address
		$ip = $_SERVER['REMOTE_ADDR'];
		$post_id = $_POST['post_id'];
		
		// Get voters'IPs for the current post
		$meta_IP = get_post_meta($post_id, "voted_IP");
		$voted_IP = $meta_IP[0];

		if(!is_array($voted_IP))
			$voted_IP = array();
		
		// Get votes count for the current post
		$meta_count = get_post_meta($post_id, "votes_count", true);

		// Use has already voted ?
		if(!hasAlreadyVoted($post_id))
		{
			$voted_IP[$ip] = time();

			// Save IP and increase votes count
			update_post_meta($post_id, "voted_IP", $voted_IP);
			update_post_meta($post_id, "votes_count", ++$meta_count);
			
			// Display count (ie jQuery return value)
			echo $meta_count;
		}
		else
			echo "already";
	}
	exit;
}

We are saving the user's IP and current time into one post_meta and votes count into another one. Time will help us to check if user can revote again after a certain elapsed time.

You could ask what happens when no vote has been recorded for the current post yet? Well, WordPress helps us one more time here, because update_post_meta checks if meta exists and creates it if not (see more information about this function on WordPress codex).

We'll define how long a user has to wait before voting again (in minutes).

$timebeforerevote = 120; // = 2 hours

This variable could be stored in theme admin panel for instance, so it's easily editable.

Now add this code to check if the user has already voted:

function hasAlreadyVoted($post_id)
{
	global $timebeforerevote;

	// Retrieve post votes IPs
	$meta_IP = get_post_meta($post_id, "voted_IP");
	$voted_IP = $meta_IP[0];
	
	if(!is_array($voted_IP))
		$voted_IP = array();
		
	// Retrieve current user IP
	$ip = $_SERVER['REMOTE_ADDR'];
	
	// If user has already voted
	if(in_array($ip, array_keys($voted_IP)))
	{
		$time = $voted_IP[$ip];
		$now = time();
		
		// Compare between current time and vote time
		if(round(($now - $time) / 60) > $timebeforerevote)
			return false;
			
		return true;
	}
	
	return false;
}

"You should always ask yourself if it's worth using a plugin and slowing down WordPress rather than adding some simple code within your theme." Wherever possible, functionality should be included via plugins, not in the theme's functions.php directly.

Nothing too complicated here, we are just checking if the user has already voted (i.e. his IP address is among votes IP's list) and if he is allowed to vote again (i.e. elapsed time since he's voted is greater than $timebeforerevote).


Step 6 Create a Function to Generate the HTML Markup

To get more control over how votes are displayed and make it easy to update if it's used in different files, we'll make a function that generates the markup. If the user has already voted, we don't display the heart as a link to avoid useless ajax calls.

function getPostLikeLink($post_id)
{
	$themename = "twentyeleven";

	$vote_count = get_post_meta($post_id, "votes_count", true);

	$output = '<p class="post-like">';
	if(hasAlreadyVoted($post_id))
		$output .= ' <span title="'.__('I like this article', $themename).'" class="like alreadyvoted"></span>';
	else
		$output .= '<a href="#" data-post_id="'.$post_id.'">
					<span  title="'.__('I like this article', $themename).'"class="qtip like"></span>
				</a>';
	$output .= '<span class="count">'.$vote_count.'</span></p>';
	
	return $output;
}

You can replace code inserted in Step 2 with this function:

<?php echo getPostLikeLink(get_the_ID());?>

Step 7 Go Further

Now users can vote on posts, you might like to get feedback. For instance, you could display a top 10 of best rated posts.

To do so, you can use query_post with these options:

query_posts('meta_key=votes_count&orderby=meta_value_num&order=DESC&posts_per_page=10');

Step 7 Conclusion

That's it! You should now be able to track your posts according to users' votes and customize both the markup and the CSS to your convenience. This is just one way to create a post rating system, among others, so don't hesitate to comment on this tutorial and give your feedback. Thank you for reading!

Related Posts
  • Code
    WordPress
    Mastering WordPress Meta Data: Understanding and Using ArraysMetadata
    In the first part of this series, we covered what WordPress meta data is, how it can be retrieved, and the various data types (such as objects or arrays) in which it can be returned. Now it's time to learn about the different types of arrays. When you write an array manually you know what its structure is an what the name of each index is. But when you are building arrays by querying a database, you are going to need to do some detective work to determine the structure of the data returned and the names of the indexes.Read More…
  • Code
    Theme Development
    Creating a WordPress Theme From Static HTML: Adding a LoopCreating wordpress theme from html 400
    In the first three parts of this series, you learned how to prepare static HTML for WordPress and to create a theme by splitting your HTML file into a set of template files and editing the stylesheet. You then uploaded your theme to WordPress and activated it. The theme still isn't displaying any content you add via the WordPress admin however; to do that you need to add a loop to your template files.Read More…
  • Code
    Plugins
    Using HighCharts in WP-AdminHighcharts 400
    Charts are a great way to present data. They make data more digestible by making it visually appealing. In WordPress, there is no built-in method for getting posts and pages data in a graphical form. Although, there are certain plugins available which integrate Google Analytics with WordPress, but they are overkill if you want to get only a portion of that data. Also, nothing should keep you from learning new techniques and to dive straight into the subject is the best way to learn.Read More…
  • Code
    Plugins
    Integrating Multiple Choice Quizzes in WordPress – Creating the FrontendIntegrating multiple choice quizzes in wordpress
    This is the second part of the series on developing a multiple choice quiz plugin for WordPress. In the first part we created the backend of our plugin to capture the necessary data to store in the database. In this final part, we will be creating the frontend of the plugin where the users can take quizzes and evaluate their knowledge.Read More…
  • Code
    Plugins
    Incorporating the jQuery Date Picker Into the Post Editor: Preparing the PluginDatepicker
    We cover a lot of topics on this blog - anything ranging from something as simple as how to include and require template files in WordPress projects to something such as an entire series on the Settings API, but I think there's always room to cover a straightforward How-To that covers a single, specific task within the context of WordPress. So, in this two-part series, we're going to take a look at how to introduce a jQuery date picker into our post editor so that we can associate a date with a given post.Read More…
  • Code
    Plugins
    Creating a Plugin to Add Votes to Your WordPress Comments Using AJAXPreview
    WordPress has a good posting system which is extendable so that WordPress can be used to build a lot of different sites rather than just a blog. WordPress also has a very extendable commenting system. The commenting system of WordPress can also be extended in different ways to be used in your WordPress sites. The commenting system can be used as a review forum if the WordPress site is to be made into a product catalog system. The commenting system can be used as answers to questions if the WordPress site is to be used for a Question and Answer site. So the commenting system in WordPress can be moulded or extended to provide functionality th at can enhance the complete site built on WordPress. In this article we are going to write a plugin to add a voting system on the comments which could be useful if the commenting system is used in a different way like in the examples stated above and many others that you can think up.Read More…