Like Dislike system with PHP and MySQL


This system works exactly like the Like/Dislike system YouTube implements for its videos. On YouTube, the buttons are placed on videos. Since we are not building the next YouTube, we will stick with using simple posts where users can click on their associated like and dislike buttons.  

We will be using:

  • Ajax of JQuery to communicate with the server without reloading the page.
  • JQuery to select elements and write values and styles and attributes on the DOM.
  • PHP to do the backend logic like receiving click actions and performing the database calls
  • MySQL as the database

Our database consists of only two tables: posts and like_dislike_info. So let's jump right in and create them, shall we!

 

Create a database called like_dislike. On your MySQL prompt, run the following commands to create the tables:

ez_ad

 

 

Table 1: posts

CREATE TABLE `posts` (
  `id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
  `text` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Table 2: rating_info

CREATE TABLE `rating_info` (
  `user_id` int(11) NOT NULL,
  `post_id` int(11) NOT NULL,
  `rating_action` varchar(30) NOT NULL,
   CONSTRAINT UC_rating_info UNIQUE (user_id, post_id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Let's populate the posts table with a few posts that we are going to be liking and disliking. Run the following commands to populate the table:

INSERT INTO `posts` (`id`, `text`) VALUES
(1, 'This is the first post'),
(2, 'This is the second piece of text'),
(3, 'This is the third post'),
(4, 'This is the fourth piece of text');

Of course, you can use a MySQL client like PHPMyAdmin to do all these database creation and populating with posts. 

Note

Make sure that on the rating_info table, the user_id and post_id fields are UNIQUE. Which means that there cannot be two records of a particular user and a particular post on the table. 

Now let's get to the coding part. The code consists of three files: 

  • index.php containing the overall markup and what is viewed in the browser and interacted with
  • server.php this is just some code that will be included in index.php
  • main.css is a file containing styling
  • scripts.js is the file containing our Jquery

Now create these three files in the root of your application and paste the following code in them:

index.php:

<?php include('server.php'); ?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Like and Dislike system</title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" />
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
  <link rel="stylesheet" href="main.css">
</head>
<body>
  <div class="posts-wrapper">
   <?php foreach ($posts as $post): ?>
        <div class="post">
      <?php echo $post['text']; ?>
      <div class="post-info">
            <!-- if user likes post, style button differently -->
        <i <?php if (userLiked($post['id'])): ?>
                  class="fa fa-thumbs-up like-btn"
          <?php else: ?>
                  class="fa fa-thumbs-o-up like-btn"
          <?php endif ?>
          data-id="<?php echo $post['id'] ?>"></i>
        <span class="likes"><?php echo getLikes($post['id']); ?></span>
        
        &nbsp;&nbsp;&nbsp;&nbsp;

            <!-- if user dislikes post, style button differently -->
        <i 
          <?php if (userDisliked($post['id'])): ?>
                  class="fa fa-thumbs-down dislike-btn"
          <?php else: ?>
                  class="fa fa-thumbs-o-down dislike-btn"
          <?php endif ?>
          data-id="<?php echo $post['id'] ?>"></i>
        <span class="dislikes"><?php echo getDislikes($post['id']); ?></span>
      </div>
        </div>
   <?php endforeach ?>
  </div>
  <script src="scripts.js"></script>
</body>
</html>
vli_ad

Let's add the styling.

main.css:

.posts-wrapper {
  width: 50%;
  margin: 20px auto;
  border: 1px solid #eee;
}
.post {
  width: 90%;
  margin: 20px auto;
  padding: 10px 5px 0px 5px;
  border: 1px solid green;
}
.post-info {
  margin: 10px auto 0px;
  padding: 5px;
}
.fa {
  font-size: 1.2em;
}
.fa-thumbs-down, .fa-thumbs-o-down {
  transform:rotateY(180deg);
}
.logged_in_user {
  padding: 10px 30px 0px;
}
i {
  color: blue;
}

server.php:

<?php 
// connect to database
$conn = mysqli_connect('localhost', 'root', '', 'dislike_like');

// lets assume a user is logged in with id $user_id
$user_id = 2;

if (!$conn) {
  die("Error connecting to database: " . mysqli_connect_error($conn));
  exit();
}

// if user clicks like or dislike button
if (isset($_POST['action'])) {
  $post_id = $_POST['post_id'];
  $action = $_POST['action'];
  switch ($action) {
        case 'like':
         $sql="INSERT INTO rating_info (user_id, post_id, rating_action) 
                   VALUES ($user_id, $post_id, 'like') 
                   ON DUPLICATE KEY UPDATE rating_action='like'";
         break;
        case 'dislike':
          $sql="INSERT INTO rating_info (user_id, post_id, rating_action) 
               VALUES ($user_id, $post_id, 'dislike') 
                   ON DUPLICATE KEY UPDATE rating_action='dislike'";
         break;
        case 'unlike':
              $sql="DELETE FROM rating_info WHERE user_id=$user_id AND post_id=$post_id";
              break;
        case 'undislike':
          $sql="DELETE FROM rating_info WHERE user_id=$user_id AND post_id=$post_id";
      break;
        default:
                break;
  }

  // execute query to effect changes in the database ...
  mysqli_query($conn, $sql);
  echo getRating($post_id);
  exit(0);
}

// Get total number of likes for a particular post
function getLikes($id)
{
  global $conn;
  $sql = "SELECT COUNT(*) FROM rating_info 
                  WHERE post_id = $id AND rating_action='like'";
  $rs = mysqli_query($conn, $sql);
  $result = mysqli_fetch_array($rs);
  return $result[0];
}

// Get total number of dislikes for a particular post
function getDislikes($id)
{
  global $conn;
  $sql = "SELECT COUNT(*) FROM rating_info 
                  WHERE post_id = $id AND rating_action='dislike'";
  $rs = mysqli_query($conn, $sql);
  $result = mysqli_fetch_array($rs);
  return $result[0];
}

// Get total number of likes and dislikes for a particular post
function getRating($id)
{
  global $conn;
  $rating = array();
  $likes_query = "SELECT COUNT(*) FROM rating_info WHERE post_id = $id AND rating_action='like'";
  $dislikes_query = "SELECT COUNT(*) FROM rating_info 
                                        WHERE post_id = $id AND rating_action='dislike'";
  $likes_rs = mysqli_query($conn, $likes_query);
  $dislikes_rs = mysqli_query($conn, $dislikes_query);
  $likes = mysqli_fetch_array($likes_rs);
  $dislikes = mysqli_fetch_array($dislikes_rs);
  $rating = [
        'likes' => $likes[0],
        'dislikes' => $dislikes[0]
  ];
  return json_encode($rating);
}

// Check if user already likes post or not
function userLiked($post_id)
{
  global $conn;
  global $user_id;
  $sql = "SELECT * FROM rating_info WHERE user_id=$user_id 
                  AND post_id=$post_id AND rating_action='like'";
  $result = mysqli_query($conn, $sql);
  if (mysqli_num_rows($result) > 0) {
        return true;
  }else{
        return false;
  }
}

// Check if user already dislikes post or not
function userDisliked($post_id)
{
  global $conn;
  global $user_id;
  $sql = "SELECT * FROM rating_info WHERE user_id=$user_id 
                  AND post_id=$post_id AND rating_action='dislike'";
  $result = mysqli_query($conn, $sql);
  if (mysqli_num_rows($result) > 0) {
        return true;
  }else{
        return false;
  }
}

$sql = "SELECT * FROM posts";
$result = mysqli_query($conn, $sql);
// fetch all posts from database
// return them as an associative array called $posts
$posts = mysqli_fetch_all($result, MYSQLI_ASSOC);
vli_ad

scripts.js:

$(document).ready(function(){

// if the user clicks on the like button ...
$('.like-btn').on('click', function(){
  var post_id = $(this).data('id');
  $clicked_btn = $(this);
  if ($clicked_btn.hasClass('fa-thumbs-o-up')) {
        action = 'like';
  } else if($clicked_btn.hasClass('fa-thumbs-up')){
        action = 'unlike';
  }
  $.ajax({
        url: 'index.php',
        type: 'post',
        data: {
                'action': action,
                'post_id': post_id
        },
        success: function(data){
                res = JSON.parse(data);
                if (action == "like") {
                        $clicked_btn.removeClass('fa-thumbs-o-up');
                        $clicked_btn.addClass('fa-thumbs-up');
                } else if(action == "unlike") {
                        $clicked_btn.removeClass('fa-thumbs-up');
                        $clicked_btn.addClass('fa-thumbs-o-up');
                }
                // display the number of likes and dislikes
                $clicked_btn.siblings('span.likes').text(res.likes);
                $clicked_btn.siblings('span.dislikes').text(res.dislikes);

                // change button styling of the other button if user is reacting the second time to post
                $clicked_btn.siblings('i.fa-thumbs-down').removeClass('fa-thumbs-down').addClass('fa-thumbs-o-down');
        }
  });           

});

// if the user clicks on the dislike button ...
$('.dislike-btn').on('click', function(){
  var post_id = $(this).data('id');
  $clicked_btn = $(this);
  if ($clicked_btn.hasClass('fa-thumbs-o-down')) {
        action = 'dislike';
  } else if($clicked_btn.hasClass('fa-thumbs-down')){
        action = 'undislike';
  }
  $.ajax({
        url: 'index.php',
        type: 'post',
        data: {
                'action': action,
                'post_id': post_id
        },
        success: function(data){
                res = JSON.parse(data);
                if (action == "dislike") {
                        $clicked_btn.removeClass('fa-thumbs-o-down');
                        $clicked_btn.addClass('fa-thumbs-down');
                } else if(action == "undislike") {
                        $clicked_btn.removeClass('fa-thumbs-down');
                        $clicked_btn.addClass('fa-thumbs-o-down');
                }
                // display the number of likes and dislikes
                $clicked_btn.siblings('span.likes').text(res.likes);
                $clicked_btn.siblings('span.dislikes').text(res.dislikes);
                
                // change button styling of the other button if user is reacting the second time to post
                $clicked_btn.siblings('i.fa-thumbs-up').removeClass('fa-thumbs-up').addClass('fa-thumbs-o-up');
        }
  });   

});

});

Now fire up the application in your browser and play around with it.

A few things to note here

  • I'm going to say this again because it is important: The user_id and post_id fields of the rating_info table must both be UNIQUE if not some of the SQL queries to the database will misbehave. 
  • We have only adapted the user login part of this app. On a full-featured application implementing the likes and dislikes system, you would have to create a users table and the user would have to log in to be able to like or dislike a post.

Conclusion

We have successfully implemented what YouTube now implements on its videos. We have used only two tables to demonstrate that which is a great feat. Not only that. We can enable a user to like or dislike a post only once and we can tell which users liked (or disliked) a particular post. We can query and display the list of all users who liked or disliked a particular post. 

So go ahead and play around with the code. Create a users table and try to stretch the features of the system we just built in this tutorial. And of course, if you have any worries or anything you didn't understand in the code, leave it in the comments and help will come.

I'd greatly appreciate it if you share this with your friends who might need it. It's a great encouragement to me.

Thanks for your time. Hope this helped. 

Happy Programming!

Awa

Related:

ez_ad


Comments