Build 5 Star Rating System with jQuery AJAX in CodeIgniter 3

Nowadays mainly in every e-commerce website, there is a rating option on the product page. User can rate the product based on its quality, usefulness, etc.

This rating is helpful for the other user who wants to purchase the product.

There are many jQuery plugins are available to add a rating bar on the page.

In this tutorial, I am using the Bootstrap star rating plugin to create rating system in the CodeIgniter 3 project.

Build 5 Star Rating System with jQuery AJAX in CodeIgniter 3


Contents

  1. Table structure
  2. Configuration
  3. Model
  4. Controller
  5. CSS
  6. View
  7. Demo
  8. Conclusion

1. Table structure

In this example, I am using two tables –

posts Table – Store post content.

CREATE TABLE `posts` (
  `id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
  `title` varchar(100) NOT NULL,
  `content` text NOT NULL,
  `link` varchar(255) NOT NULL
);

posts_rating Table – Use to store users rating on the posts.

CREATE TABLE `posts_rating` (
  `id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
  `userid` int(11) NOT NULL,
  `postid` int(11) NOT NULL,
  `rating` int(2) NOT NULL
);

2. Configuration

Navigate to application/config/database.php and define the Database connection.

$db['default'] = array(
   'dsn' => '',
   'hostname' => 'localhost',
   'username' => 'root', // Username
   'password' => '', // Password
   'database' => 'tutorial', // Database name
   'dbdriver' => 'mysqli',
   'dbprefix' => '',
   'pconnect' => FALSE,
   'db_debug' => (ENVIRONMENT !== 'production'),
   'cache_on' => FALSE,
   'cachedir' => '',
   'char_set' => 'utf8',
   'dbcollat' => 'utf8_general_ci',
   'swap_pre' => '',
   'encrypt' => FALSE,
   'compress' => FALSE,
   'stricton' => FALSE,
   'failover' => array(),
   'save_queries' => TRUE
);

Default controller

Open application/config/routes.php and edit default_controller value to Posts.

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

Load Database

To access the MySQL database require loading database library.

Open application/config/autoload.php and add the database in libraries array().

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

3. Model

Create a new Main_model.php file in application/models/ directory.

Here, create 3 methods –

  • __construct
  • getAllPosts – Fetch all records from posts table and also calculate average rating and user rating on a post from posts_rating table.

Initialize $posts_arr with fetched records and return it.

  • userRating – Using this method update user rating. Check the user record on the posts_rating table. If a record does not exist then insert record otherwise update rating field on posts_rating table.

Calculate the average rating on a post and return it.

Completed Code

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

Class Main_model extends CI_Model {

   public function __construct() {
        parent::__construct(); 
   }

   // Fetch records
   public function getAllPosts($userid) {

        // Posts
        $this->db->select('*');
        $this->db->from('posts');
        $this->db->order_by("id", "asc");
        $postsquery = $this->db->get();

        $postResult = $postsquery->result_array();

        $posts_arr = array();
        foreach($postResult as $post){
             $id = $post['id'];
             $title = $post['title'];
             $link = $post['link'];
             $content = $post['content'];

             // User rating
             $this->db->select('rating');
             $this->db->from('posts_rating');
             $this->db->where("userid", $userid);
             $this->db->where("postid", $id);
             $userRatingquery = $this->db->get();

             $userpostResult = $userRatingquery->result_array();

             $userRating = 0;
             if(count($userpostResult)>0){
                   $userRating = $userpostResult[0]['rating'];
             }

             // Average rating
             $this->db->select('ROUND(AVG(rating),1) as averageRating');
             $this->db->from('posts_rating');
             $this->db->where("postid", $id);
             $ratingquery = $this->db->get();

             $postResult = $ratingquery->result_array();

             $rating = $postResult[0]['averageRating'];

             if($rating == ''){
                   $rating = 0;
             }

             $posts_arr[] = array("id"=>$id,"title"=>$title,"content"=>$content,"link"=>$link,"rating"=>$userRating,"averagerating"=>$rating);
        }

        return $posts_arr;
   }

   // Save user rating
   public function userRating($userid,$postid,$rating){
        $this->db->select('*');
        $this->db->from('posts_rating');
        $this->db->where("postid", $postid);
        $this->db->where("userid", $userid);
        $userRatingquery = $this->db->get();

        $userRatingResult = $userRatingquery->result_array();
        if(count($userRatingResult) > 0){

             $postRating_id = $userRatingResult[0]['id'];
             // Update
             $value=array('rating'=>$rating);
             $this->db->where('id',$postRating_id);
             $this->db->update('posts_rating',$value);
        }else{
             $userRating = array(
                  "postid" => $postid,
                  "userid" => $userid,
                  "rating" => $rating
             );

             $this->db->insert('posts_rating', $userRating);
        }

        // Average rating
        $this->db->select('ROUND(AVG(rating),1) as averageRating');
        $this->db->from('posts_rating');
        $this->db->where("postid", $postid);
        $ratingquery = $this->db->get();

        $postResult = $ratingquery->result_array();

        $rating = $postResult[0]['averageRating'];

        if($rating == ''){
              $rating = 0;
        }

        return $rating;
   }

}

4. Controller

Create a new Posts.php file in application/controllers/ directory.

Here, create 3 methods –

  • __construct – Load url helper, session library and Main_model model. Define userid SESSION variable and assign 3.
  • index – Call Main_model model getAllPosts() method to fetch all records. Load post_view view and pass $data.
  • updateRating – This method is call from jQuery AJAX where rating changed by the user.

Read POST values and pass in userRating() method to update the user rating.

Return the $averageRating.

Completed Code

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

class Posts extends CI_Controller {

  public function __construct(){

    parent::__construct();
    $this->load->helper('url');

    // Load session
    $this->load->library('session');

    // Load model
    $this->load->model('Main_model');

    // Userid 
    $this->session->set_userdata(array("userid"=>3));

  }

  public function index(){

    $data = array();

    // Userid
    $userid = $this->session->userdata('userid');

    // Fetch all records
    $data['posts'] = $this->Main_model->getAllPosts($userid);

    // Load view
    $this->load->view('post_view',$data);
  }

  // Update rating
  public function updateRating(){

    // userid
    $userid = $this->session->userdata('userid');

    // POST values
    $postid = $this->input->post('postid');
    $rating = $this->input->post('rating');

    // Update user rating and get Average rating of a post
    $averageRating = $this->Main_model->userRating($userid,$postid,$rating);

    echo $averageRating;
    exit;
  }

}

5. CSS

Create a assets directory at project root.

Now create a style.css file and store in assets directory.

.content{
    border: 0px solid black;
    border-radius: 3px;
    padding: 5px;
    margin: 0 auto;
    width: 50%;
}

.post{
    border-bottom: 1px solid black;
    padding: 10px;
    margin-top: 10px;
    margin-bottom: 10px;
}
.post:last-child{
    border: 0;
}

.post h2{
    font-weight: normal;
    font-size: 30px;
}

.post a.link{
    text-decoration: none;
    color: black;
}
.post-text{
    letter-spacing: 1px;
    font-size: 15px;
    font-family: serif;
    color: gray;
    text-align: justify;
}
.post-action{
    margin-top: 15px;
    margin-bottom: 15px;
}

6. View

Create a new post_view.php file in application/views/ directory.

Download Bootstrap Start Rating plugin –

  • Download the plugin from here.
  • Extract the zip file in assets directory which created in the previous step.

Layout –

Include CSS and JS of Bootstrap star rating plugin along with bootstrap.min.css, font-awesome.min.css, style.css, and jQuery library in the <head > section.

Loop on $posts array and create posts list.

Add rating bar using input element where add class='rating-loading ratingbar' date-min='0' data-max='5'. Pass $rating in the value attribute.

Script –

Initialize rating on $('.ratingbar') where define showCaption: false, showClear: false, size: 'sm'.

Also define change event on $('.ratingbar').

Split the id to get the postid and send AJAX POST request to index.php/posts/updateRating. Pass postid and rating as data.

On successful callback update the post average rating text by passing response in $('#averagerating_'+postid).text(response).

Completed Code

<?php
defined('BASEPATH') OR exit('No direct script access allowed');
?>
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Build 5 Star Rating System with jQuery AJAX in CodeIgniter 3</title>

    <!-- Bootstrap CSS -->
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">

    <!-- Font awesome -->
    <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">

    <!-- Bootstrap Star Rating CSS -->
    <link href='<?= base_url() ?>assets/bootstrap-star-rating/css/star-rating.min.css' type='text/css' rel='stylesheet'>

    <!-- Custom CSS -->
    <link href="<?= base_url() ?>assets/style.css" rel="stylesheet">

    <!-- jQuery Library -->
    <script src='<?= base_url() ?>assets/js/jquery-3.3.1.js' type='text/javascript'></script>

    <!-- Bootstrap Star Rating JS -->
    <script src='<?= base_url() ?>assets/bootstrap-star-rating/js/star-rating.min.js' type='text/javascript'></script>

  </head>
  <body>

    <div class='content'>

      <!-- Post List -->
      <?php 
      foreach($posts as $post){
        $id = $post['id'];
        $title = $post['title'];
        $content = $post['content'];
        $link = $post['link'];
        $rating = $post['rating']; // User rating on a post
        $averagerating = $post['averagerating']; // Average rating

      ?>
      <div class="post">
        <h2><a href='<?= $link ?>' class='link' target='_blank'><?= $title; ?></a></h2>
        <div class="post-text">
          <?= $content; ?>
        </div>
        <div class="post-action">

          <!-- Rating Bar -->
          <input id="post_<?= $id ?>" value='<?= $rating ?>' class="rating-loading ratingbar" data-min="0" data-max="5" data-step="1">

          <!-- Average Rating -->
          <div >Average Rating: <span id='averagerating_<?= $id ?>'><?= $averagerating ?></span></div>
        </div>
      </div>
      <?php
      }
      ?>

    </div>

    <!-- Script -->
    <script type='text/javascript'>
    $(document).ready(function(){

      // Initialize
      $('.ratingbar').rating({
        showCaption:false,
        showClear: false,
        size: 'sm'
      });

      // Rating change
      $('.ratingbar').on('rating:change', function(event, value, caption) {
        var id = this.id;
        var splitid = id.split('_');
        var postid = splitid[1];

        $.ajax({
          url: '<?= base_url() ?>index.php/employee/updateRating',
          type: 'post',
          data: {postid: postid, rating: value},
          success: function(response){
             $('#averagerating_'+postid).text(response);
          }
        });
      });
    });
 
    </script>

  </body>
</html>

7. Demo

Change the rating. View in a new tab.


7. Conclusion

For the example purpose, I fixed the SESSION userid variable value to 3. Use your SESSION variable while implementing this on your project.

You need to pass rating value in the input element and initialize rating() on the selector to create the rating bar.

You can also view this tutorial to know rating system implementation on CodeIgniter 4.

If you found this tutorial helpful then don't forget to share.