Codeigniter, AJAX Voting/Rating System

Introduction

In this post we will see how to create voting or rating system using Codeigniter, MySQL and AJAX. We post tutorials, articles or blogs either to our own blog site or as a user to other sites. Sometimes we need to let user rate on our tutorials or articles or blogs so that we know how much that blog is famous or how much that blog is intended to be accepted by readers.

In this example I have given one sample content on which you can rate this.

The rating/voting system is calculated by taking average on accumulated votes on five stars. Once you give vote/rate from your system you cannot give vote or rate next time.

As soon as you cast your vote or rate you can see it instantly the updated vote as well as you can also see what vote/rate you have cast.

When you mouse over on stars you can see the highlighted stars on how many stars vote/rate you want to cast.

Prerequisites

Apache HTTP Server 2.4, PHP 7.3.5, Codeigniter 3.1.10, MySQL 8.0.17

Creating Project Directory

It’s assumed that you have setup Apache 2.4, PHP 7.3.5 and Codeigniter 3.1.10 in Windows system.

Now we will create a project root directory called codeIgniter-ajax-mysql-voting-rating-app under the Apache server’s htdocs folder.

Now move all the directories and files from CodeIgniter 3.1.10 framework into codeIgniter-ajax-mysql-voting-rating-app directory.

We may not mention the project root directory in subsequent sections and we will assume that we are talking with respect to the project’s root directory.

You need to create assets folder in parallel to application folder for putting all asset files such as js, css, images etc.

Final Results

When you run the application by hitting the URL: http://localhost/codeIgniter-ajax-mysql-voting-rating-app/index.php

Codeigniter AJAX vote/rate system

When you mouse over stars:

Codeigniter AJAX vote/rate system

When you rate the blog:

Codeigniter AJAX vote/rate system

Create MySQL Table

First thing is we need to create database table where rating or voting will be stored.

CREATE TABLE `blog_vote` (
  `vote_id` int unsigned NOT NULL AUTO_INCREMENT,
  `blog_vote` float NOT NULL,
  `blog_id` int unsigned NOT NULL,
  `ip_address` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`vote_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

Database Configuration

Configure database settings at location application/config/database.php. Make sure to update the configurations according to your project.

'hostname' => 'localhost',
'username' => 'root',
'password' => 'root',
'database' => 'roytuts',
'dbdriver' => 'mysqli',
...
'char_set' => 'utf8mb4',
'dbcollat' => 'utf8mb4_unicode_ci',

Configuring Auto-load

Configure auto-load to avoid loading resources whenever required for the application at location application/config/autoload.php as follows:

$autoload['libraries'] = array('database');

$autoload['helper'] = array('url');

Creating Model Class

Create a model which will give us the data for the vote/rate from database. We are also going to store vote or rate for a blog into the database through this model class at application/models/VotingRating_Model.php.

<?php

if (!defined('BASEPATH'))
exit('No direct script access allowed');

/**
* Description of VotingRating_Model
*
* @author https://roytuts.com
*/

class VotingRating_Model extends CI_Model {

	private $blog_vote = 'blog_vote';

    function get_blog_rating($blog_id) {
        $sql = 'SELECT COUNT(DISTINCT(bv.vote_id)) total_rows,
            IFNULL(SUM(bv.blog_vote),0) total_rating, bv.blog_id
            FROM ' . $this->blog_vote . ' bv
            WHERE bv.blog_id=' . $blog_id . ' LIMIT 1';

        $query = $this->db->query($sql);
        $row = $query->row();
        $total_rows = $row->total_rows;
        $total_rating = $row->total_rating;
        $results['vote_rows'] = $total_rows;
        
		$rating = 0;
		
        if ($total_rows > 0) {
            $rating = $total_rating / $total_rows;
        }
		
        $dec_rating = round($rating, 1);
        $results['vote_rate'] = $rating;
        $results['vote_dec_rate'] = $dec_rating;
		
        return $results;
    }

    function get_blog_rating_from_ip($blog_id) {
        $ip = $this->input->ip_address();
        $sql = 'SELECT bv.vote_id
            FROM ' . $this->blog_vote . ' bv
            WHERE bv.ip_address=' . $this->db->escape($ip) .
                ' AND bv.blog_id=' . $blog_id;

        $this->db->limit(1);
        $query = $this->db->query($sql);
		
        if ($query->num_rows() > 0) {
            $row = $query->row();
            $vote_id = $row->vote_id;
			
            $sql = 'SELECT IFNULL(SUM(bv.blog_vote),0) total_rating,
                bv.blog_id
                FROM ' . $this->blog_vote . ' bv  
                WHERE bv.blog_id=' . $blog_id .
                    ' LIMIT 1';
					
            $query = $this->db->query($sql);
			
            $row = $query->row();
            $rating = $row->total_rating;
            $rating = round($rating, 1);
            $results['vote_rate'] = $rating;
			
            return $results;
        }
    }

    /*
     * rate this blog
     */

    function rate_blog($blog_id, $rating) {
        $ip = $this->input->ip_address();
        $sql = 'SELECT bv.vote_id
            FROM ' . $this->blog_vote . ' bv
            WHERE bv.ip_address=' . $this->db->escape($ip) .
                ' AND bv.blog_id=' . $blog_id;

        $this->db->limit(1);
        $query = $this->db->query($sql);
		
        if ($query->num_rows() > 0) {
            $row = $query->row();
            $vote_id = $row->vote_id;
			
            $sql = 'SELECT IFNULL(SUM(bv.blog_vote),0) total_rating,
                bv.blog_id
                FROM ' . $this->blog_vote . ' bv
                WHERE bv.vote_id=' . $vote_id . '
                AND bv.blog_id=' . $blog_id .
                    ' LIMIT 1';

            $query = $this->db->query($sql);
            $row = $query->row();
            $rating = $row->total_rating;
            $rating = round($rating, 1);
            $results['vote_curr_rate'] = $rating;
        } else {
            //$this->db->trans_start(TRUE);
            $data = array(
                'blog_vote' => $rating,
                'blog_id' => $blog_id,
                'ip_address' => $ip
            );
            $this->db->insert($this->blog_vote, $data);
            //$this->db->trans_complete();
			
			//echo '$this->db->trans_status(): ' . $this->db->trans_status();
			
            /*if ($this->db->trans_status() === FALSE) {
                $this->db->trans_rollback();
            } else {
                $this->db->trans_commit();*/
				
                $sql = 'SELECT IFNULL(SUM(bv.blog_vote),0) total_rating,
                bv.blog_id
                FROM ' . $this->blog_vote . ' bv
                WHERE bv.blog_id=' . $blog_id .
                        ' LIMIT 1';

                $query = $this->db->query($sql);
				
                $row = $query->row();
                $rating = $row->total_rating;
                $rating = round($rating, 1);
                $results['vote_curr_rate'] = $rating;
            //}
        }
		
        $overall_results = $this->get_blog_rating($blog_id);
        $results['vote_rows'] = $overall_results['vote_rows'];
        $results['vote_rate'] = $overall_results['vote_rate'];
        $results['vote_dec_rate'] = $overall_results['vote_dec_rate'];
		
        return $results;
    }

}

We will create a controller called VotingRatingController under application/controller directory with below code.

The controller class is responsible for handling request/response for the clients.

This class loads the model class to pass data between database and clients.

<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class VotingRatingController extends CI_Controller {

	function __construct() {
        parent::__construct();
        $this->load->model('VotingRating_Model', 'vr');
    }

    function index() {
        //the hard-coded blog id value 1 should come from UI
        $blog_id = 1;
        $vote_results = $this->vr->get_blog_rating($blog_id);
        $data['blog_vote_overall_rows'] = $vote_results['vote_rows'];
        $data['blog_vote_overall_rate'] = $vote_results['vote_rate'];
        $data['blog_vote_overall_dec_rate'] = $vote_results['vote_dec_rate'];
		
        $vote_results = $this->vr->get_blog_rating_from_ip($blog_id);
        $data['blog_vote_ip_rate'] = $vote_results['vote_rate'];
		
        $this->load->view('voting-rating', $data);
    }

    function rate_blog() {
        if (isset($_POST)) {
            $blog_id = $_POST['blog_id'];
            $rating = $_POST['rating'];
			
			//echo $blog_id . ' ' . $rating;
			
            $vote_results = $this->vr->rate_blog($blog_id, $rating);
			
			//print_r($vote_results);
			
            $blog_vote_overall_rows = $vote_results['vote_rows'];
            $blog_vote_overall_rate = $vote_results['vote_rate'];
            $blog_vote_overall_dec_rate = $vote_results['vote_dec_rate'];
            $blog_vote_ip_rate = $vote_results['vote_curr_rate'];
            $stars = '';
            for ($i = 1; $i <= floor($blog_vote_overall_rate); $i++) {
                $stars .= '<div class="star" id="' . $i . '"></div>';
            }
            //THE OVERALL RATING (THE OPAQUE STARS)
            echo '<div class="r"><div class="rating">' . $stars . '</div>' .
            '<div class="transparent">
                <div class="star" id="1"></div>
                <div class="star" id="2"></div>
                <div class="star" id="3"></div>
                <div class="star" id="4"></div>
                <div class="star" id="5"></div>
                <div class="votes">(' . $blog_vote_overall_dec_rate . '/5, ' . $blog_vote_overall_rows . ' ' . ($blog_vote_overall_rows > 1 ? ' votes' : ' vote') . ') ' . ($blog_vote_ip_rate > 0 ? '<strong>You rated this: <span style="color:#39C;">' . $blog_vote_ip_rate . '</span></strong>' : '') . '</div>
              </div>
            </div>';
        }
    }
}

Configuring Route

Now modify the application/config/routes.php file to configure the default controller class that will be loaded on loading of the context root of the application.

$route['default_controller'] = 'VotingRatingController';

Creating View File

Next is to display the blog post and rating or voting stars on the page so that end users will be able to cast his/her vote or rate on a particular post.

Write the below code into a file application/views/voting-rating.php file.

In this page I have hard-coded one blog with sample text. Ideally your blogs should come from a persistence storage, such as, database or file or external system.

I have used latest version of jQuery from CDN and older version is in the source code.

<?php
$overall_vote_rows = $blog_vote_overall_rows;
$overall_vote_rate = $blog_vote_overall_rate;
$overall_vote_dec_rate = $blog_vote_overall_dec_rate;
$ip_vote_rate = $blog_vote_ip_rate;
?>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8"/>
        <title>Voting Rating System using Codeigniter MySQL AJAX</title>
        <!--[if IE]> <script> (function() { var html5 = ("abbr,article,aside,audio,canvas,datalist,details," + "figure,footer,header,hgroup,mark,menu,meter,nav,output," + "progress,section,time,video").split(','); for (var i = 0; i < html5.length; i++) { document.createElement(html5[i]); } try { document.execCommand('BackgroundImageCache', false, true); } catch(e) {} })(); </script> <![endif]-->
        <link type="text/css" rel="stylesheet" href="<?php echo base_url(); ?>assets/css/blog_rating.css"/>
        <!--<script type= 'text/javascript' src="<?php echo base_url(); ?>assets/js/jquery-1.9.1.min.js"></script>-->
		<script type="text/javascript" src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
        <script type= 'text/javascript' src="<?php echo base_url(); ?>assets/js/blog_rating.js"></script>
    </head>
    <body>
        <div class='singlepost'>
            <div class='fullpost clearfix'>
                <div class='entry'>
                    <h1 class='post-title'>
                        This is a sample blog content
                    </h1>
                    <p>
                        Posted By: roytuts.com,  
                        Posted On: 25-08-2015
                    </p>
                    <input type="hidden" name="blog_content_id" id="blog_content_id" value="1"/>
                    <?php
                    $stars = '';
                    echo '<div id="ajax_vote">';
                    for ($i = 1; $i <= floor($overall_vote_rate); $i++) {
                        $stars .= '<div class="star" id="' . $i . '"></div>';
                    }
                    //THE OVERALL RATING (THE OPAQUE STARS)
                    echo '<div class="r"><div class="rating">' . $stars . '</div>';

                    //THE TRANSPARENT STARS (OPAQUE STARS WILL COVER AS MANY STARS AS THE RATING REPRESENTS)
                    echo '<div class="transparent">
						<div class="star" id="1"></div>
						<div class="star" id="2"></div>
						<div class="star" id="3"></div>
						<div class="star" id="4"></div>
						<div class="star" id="5"></div>
						<div class="votes">(' . $blog_vote_overall_dec_rate . '/5, ' . $overall_vote_rows . ' ' . ($overall_vote_rows > 1 ? ' votes' : ' vote') . ') ' . ($blog_vote_ip_rate > 0 ? '<strong>You rated this: <span style="color:#39C;">' . $blog_vote_ip_rate . '</span></strong>' : '') . '</div>
					  </div>
					</div>';
                    echo '</div>';
                    ?>
                    <div> </div>
                    <p style="text-align: justify;">
                        The topic of blogging seems to come up a lot in our social media training workshops. The benefits of a quality blog are obvious – fresh content is good for your readers and your rankings. Blogs are easy to set up and even easier to update. We often tell people that if they can use Microsoft Word… they can update a blog.

                        As easy as they are to set up, they can be difficult to maintain. A good blog is filled with relevant, timely content that is updated on a regular basis. New bloggers often start out with a bang but then fizzle out when they realize that creating content can be challenging.
                    </p>
                </div>
            </div>
        </div>
    </body>
</html>

Running and Testing the Application

I assume that you have started your Apache 2.4 Server and your CodeIgniter application will automatically be started.

Now you can test the application by hitting the specified URL as mentioned in section Final Results.

You can download source code.

That’s all. Thanks for reading.

2 thoughts on “Codeigniter, AJAX Voting/Rating System

Leave a Reply

Your email address will not be published. Required fields are marked *