Like and dislike system in PHP and AJAX with MYSQL database


The like and dislike system is used to decide which post content is good and bad. Users always give a like if the post content is good and Users give a dislike if the post content is not valuable (bad for users). In this tutorial, we will create a like and dislike system in PHP and AJAX. The like and dislike system will be the same like as Youtube and Facebook social websites. A user can like and unlike or dislike and undislike post content. We will create the same Youtube and Facebook like and dislike system in PHP, MYSQL, AJAX, jQuery, bootstrap, and PHP PDO prepared statement. It will be a more secure and smooth working system. 

like and dislike system like Facebook and Youtube

How to create like and dislike system in PHP and AJAX – 

Like and dislike feature is one of the famous feature for social sites like Facebook, Twitter, LinkedIn, etc. 
You can create this system for blog posts, products, and digital items. Most of the biggest eCommerce websites are using like and dislike features. These websites are Flipkart, Amazon, etc. Now, let’s discuss the process.

First of all, we create MYSQL database tables for users, posts, and user ratings. The “users” table will be used to login users and register users because the like and dislike system works after login. We will fetch all posts from the posts database table and display them in the list on the index page with the like and dislike icons. 
When a user will like or dislike any post the post id and rating_action (like, and dislike) will be inserted into the user rating database table. 
Let’s create like and dislike feature in PHP – 
First of all, create three MYSQL database tables using below queries – 
 Create a table "posts" – 

CREATE TABLE `posts` (
  `post_id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
  `title` varchar(355) DEFAULT NULL,
  `content` longtext DEFAULT NULL
) ;

Insert some posts – 

INSERT INTO `posts` (`post_id`, `title`, `content`) VALUES
(1, 'How to use AJAX, and Jquery with PHP programming?', 'As you know that Ajax is used to create CRUD operations without page refreshing and Jquery is one of the best framework of Javascript. We will create an upvote and downvote system with ajax, PHP, jquery, and the MYSQL database.'),
(2, 'Like and dislike system in PHP ', 'A QA forum can\'t be completed without a rating system. Using this upvote and downvote system, users can vote on questions or posts. Users can give upvotes or downvotes.'),
(3, 'How to create a like and dislike system using PHP, AJAX, and MYSQL database?', 'The like and dislike system is one of the most useful systems for blogs, QA forums, and other content based websites or events.'),
(4, 'How to create an rating system in PHP, AJAX, Jquery, and MYSQL?', 'In this tutorial post, we learn the rating system in PHP, AJAX, and JQUERY with the MYSQL database. ');

As we already discussed above that we will fetch and display these posts from the posts table on the index page and single post page by id with like and dislike icons. Users can like or dislike from the index page or single post page. 
Now, create a users table – 

CREATE TABLE `users` (
  `id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
  `username` varchar(255) DEFAULT NULL,
  `email` varchar(255) DEFAULT NULL,
  `password` varchar(355) DEFAULT NULL
);

We will create a registration and login system to like and dislike the post
Now, create a user_rating table – 

CREATE TABLE `user_rating` (
  `userid` int(11) NOT NULL,
  `postid` int(11) NOT NULL,
  `rating_action` varchar(30) NOT NULL
) ;
ALTER TABLE `user_rating`
  ADD UNIQUE KEY `UC_user_rating` (`userid`,`postid`);

In this MYSQL database table, we will insert post id and rating_action like and dislike. 

Now, we will create a connection file. As you know, we will use the PHP PDO connection string to connect the MYSQL database.
Let’s create a connection file- 
config.php 

<?php session_start();
define('DBNAME','web');
define('DBUSER','root');
define('DBPASS','');
define('DBHOST','localhost');
try {
  $db = new PDO("mysql:host=".DBHOST.";dbname=".DBNAME, DBUSER, DBPASS);
  $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  //echo "Your page is connected with database successfully..";
} catch(PDOException $e) {
  echo "Issue -> Connection failed: " . $e->getMessage();
}
?>

Kindly set all credentials according to your database. 
We always work in a sequence. A connection file has been created. Now, will create an index file in PHP. 
This is our project home page or index page. We will fetch all posts from the database and display them with like and dislike icons using the font-awesome library. 
index.php

<?php require_once("config.php");
if(!isset($_SESSION['login_session'])){ 
	header("location:login.php");
}
else 
{
	$userid=$_SESSION['userid'];
    include("functions.php");
}
?>
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>Like Dislike (Unlike) system in PHP and AJAX</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="style.css">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" />
<script src="like_dislike.js"></script>
</head>
<body>
<div class="container">
	<div div class="row">
	<div style="background:grey; color: #fff;" class="card">
	 	<h1>All Posts </h1>	<a href="logout.php">Logout</a>
	</div>
</div>
<br>
    <div class="row">
    	<?php 

         $sql="SELECT * FROM posts ORDER BY post_id DESC"; 
          $stmt=$db->prepare($sql);
            $stmt->execute();
$rows=$stmt->fetchAll();
foreach($rows as $row)
{

?> 
<div class="col-sm-2"></div>
<div class="col-sm-8 list">
	  <div class="row card_item ">
	  	<div class="col-sm-12">
     <li class="title"><a href="post.php?id=<?php echo $row['post_id'];?>"><?php echo $row["title"]; ?></a></li>
     <div class="content"><?php echo $row['content']?> </div> 
 </div>
 <div class="col-sm-12">
        <i <?php
         if(userLikesDislikes($row['post_id'],$userid,'like',$db)): ?>
              class="fa fa-thumbs-up like-btn"
          <?php else: ?>
              class="fa fa-thumbs-o-up like-btn"
          <?php endif ?>
          data-id="<?php echo $row['post_id'] ?>"></i>
        <span class="likes"><?php echo getLikesDislikes($row['post_id'],'like',$db); ?></span>
        
        &nbsp;&nbsp;&nbsp;&nbsp;
        <i 
          <?php if (userLikesDislikes($row['post_id'],$userid,'dislike',$db)): ?>
              class="fa fa-thumbs-down dislike-btn"
          <?php else: ?>
              class="fa fa-thumbs-o-down dislike-btn"
          <?php endif ?>
          data-id="<?php echo $row['post_id'] ?>"></i>
        <span class="dislikes"><?php echo getLikesDislikes($row['post_id'],'dislike',$db); ?></span>

 </div>

     </div>
 </div>
 <div class="col-sm-2"></div>
<?php }
    	?> 
    </div>
</div>
</body>
</html>

In the above code, we fetched and display all posts from the database to the index page with like and dislike icons. As you can see, we are using PHP PDO-prepared statements to avoid SQL injection.  
You cannot visit the index page without the login and register page. Now, we will create a login and registration form. 
First of all, create a login form. Users can log in to this form and can like, and unlike and dislike, undislike any posts

login.php 

<?php require_once("config.php");?>
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>Login</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="container">
	<div div class="row">
	<div style="background:grey; color: #fff;" class="card">
	 	<h1>Login to like and dislike..</h1>	
	</div>
</div>
<br>
    <div class="row"> 
    	<div class="col-sm-3">
    	</div>
    	<div class="col-sm-6">
    		<?php 
    		if(isset($_POST['login_submit']))
    		{
    			$login_var=$_POST['login_var']; 
    			$password=$_POST['password'];
    			$sql= "SELECT count(*) FROM users WHERE username=:login_var OR email=:login_var"; $stmt = $db->prepare($sql);
       $stmt->bindParam(':login_var', $login_var ,PDO::PARAM_STR);
    $stmt->execute();

        $count= $stmt->fetchColumn(); 
        if($count>0)
        {
        	 $sql="SELECT id,password FROM users WHERE username=:login_var OR email=:login_var"; $stmt=$db->prepare($sql);
        	 $stmt->bindParam(':login_var', $login_var ,PDO::PARAM_STR);
            $stmt->execute();
$row=$stmt->fetch();
if(password_verify($password,$row['password'])){
           $_SESSION["login_session"]="1";
           $_SESSION["userid"]=$row['id'];
  header("location:index.php");
        }
        else{
       echo 'Invalid Username or Password';
        }
        }
        else 
        {
        	echo 'Invalid Username or Password';
        }
    		}
    		?> 
    		<form action="" method="post">
  <div class="form-group">
    <label>Username or Email</label>
    <input type="text" class="form-control" placeholder="Username or email" name="login_var" required>
  </div>
  <div class="form-group">
    <label>Password</label>
    <input type="password" class="form-control" placeholder="Password" name="password" required>
  </div>
  <div class="form-group form-check">
  </div>
  <button type="submit" class="btn btn-primary" name="login_submit">Login </button>
</form>
<br> 
OR 
<a href="register.php">Register</a>
    	</div>
    	<div class="col-sm-3">
    	</div>
    </div>
</div>
</body>
</html>

It’s very easy to create a login form. We already discussed the login and registration system in PHP
Now, create a registration form in PHP. 
register.php

<?php require_once("config.php");?>
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>Register </title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="container">
	<div div class="row">
	<div style="background:grey; color: #fff;" class="card">
	 	<h1>Register</h1>	
	</div>
</div>
<br>
    <div class="row"> 
    	<div class="col-sm-3">
    	</div>
    	<div class="col-sm-6">
    		<?php 
    		if(isset($_POST['login_submit']))
    		{
    			$username=$_POST['username']; 
    			$password=$_POST['password'];
                $email=$_POST['email'];
        	 $sql="INSERT INTO users(username,email,password) VALUES(:username,:email,:password)"; 
             $stmt=$db->prepare($sql);
                    $options = array("cost"=>4);
    $password = password_hash($password,PASSWORD_BCRYPT,$options);

        	 $stmt->bindParam(':username', $username ,PDO::PARAM_STR);
              $stmt->bindParam(':email', $email ,PDO::PARAM_STR);
              $stmt->bindParam(':password', $password ,PDO::PARAM_STR);
            $res=$stmt->execute();
            if($res)
            {
                echo 'You have successfully registered. <a href="login.php">Login Here</a>';
            }
            else 
            {
               echo 'Something wrong'; 
            }
    		}
    		?> 
    		<form action="" method="post">
  <div class="form-group">
    <label>Username</label>
    <input type="text" class="form-control" placeholder="Username" name="username" required>
  </div>
  <div class="form-group">
    <label>Email </label>
    <input type="email" class="form-control" placeholder="Username" name="email" required>
  </div>

  <div class="form-group">
    <label>Password</label>
    <input type="password" class="form-control" placeholder="Password" name="password" required>
  </div>
  <div class="form-group form-check">
  </div>
  <button type="submit" class="btn btn-primary" name="login_submit">Register</button>
</form>
<br> 
OR 
<a href="login.php">Login</a>

    	</div>
    	<div class="col-sm-3">
    	</div>
    </div>
</div>
</body>
</html>

In the above code, you can see, we are using bootstrap to make a responsive form. 
Now, you can register and log in with the same username or email and password. 
You can visit the index page after login in. 
You will need to design your page. Create a stylesheet. We already linked the stylesheet on all pages. 
style.css

li{
	color: #000000;
	text-decoration: none;
	font-size: 20px;
	list-style-type: none; 
}
.list{
	padding-bottom: 20px;
}
.card {
	padding: 5px;
}
.content{
	font-size: 14px;
}

.card_item { border: 1px solid black;}
options{
    cursor: pointer;	
}
.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;
 cursor: pointer; 
}

a{
	color: #000000;
	text-decoration: none;
	font-size: 20px; 
}

If the stylesheet does not apply then please clear the history and cache of your browser also check the style.css link in the view source code feature.
You will get errors like undefined methods or functions. To remove these errors, you will need to create a functions.php file. 
All functions will be available in the functions.php file. This will help us to reduce code lines.
functions.php 

<?php 
function userLikesDislikes($postid,$userid,$rating_action,$db)
{
        $sql="SELECT COUNT(*) FROM user_rating WHERE userid=:userid 
        AND postid=:postid AND rating_action=:rating_action";
         $stmt = $db->prepare($sql);
 $stmt->bindParam(':userid', $userid, PDO::PARAM_INT);
    $stmt->bindParam(':postid', $postid, PDO::PARAM_INT);
      $stmt->bindParam(':rating_action', $rating_action, PDO::PARAM_STR);
       $stmt->execute();
$count = $stmt->fetchColumn();
  if ($count > 0) {
    return true;
  }else{
    return false;
  }
}
function getLikesDislikes($postid,$rating_action,$db)
{
     $sql="SELECT COUNT(*) FROM user_rating WHERE postid = :postid AND rating_action=:rating_action";
          $stmt = $db->prepare($sql);
    $stmt->bindParam(':postid', $postid, PDO::PARAM_INT);
      $stmt->bindParam(':rating_action', $rating_action, PDO::PARAM_STR);
 $stmt->execute();
        $number_of_rows = $stmt->fetchColumn(); 
        return $number_of_rows;  
}
function insert_vote($userid,$postid,$rating_action,$db){
         $sql="INSERT INTO user_rating(userid, postid, rating_action) 
             VALUES (:userid, :postid, :rating_action) 
             ON DUPLICATE KEY UPDATE rating_action=:rating_action";
     $stmt = $db->prepare($sql); 
       $stmt->bindParam(':userid', $userid, PDO::PARAM_INT);
       $stmt->bindParam(':postid', $postid, PDO::PARAM_INT);
       $stmt->bindParam(':rating_action', $rating_action, PDO::PARAM_STR);
    $stmt->execute();
      }
      function delete_vote($userid,$postid,$db){
         $sql="DELETE FROM user_rating WHERE userid=:userid AND postid=:postid";
     $stmt = $db->prepare($sql); 
       $stmt->bindParam(':userid', $userid, PDO::PARAM_INT);
       $stmt->bindParam(':postid', $postid, PDO::PARAM_INT);
    $stmt->execute();
      }
      function getRating($postid,$db)
{
  $rating = array();
     $likes=getLikesDislikes($postid,'like',$db);
     $dislikes=getLikesDislikes($postid,'dislike',$db);
  $rating = [
    'likes' => $likes,
    'dislikes' => $dislikes
  ];
  return json_encode($rating);
}
?> 

In the above PHP file, there are many functions created like counting user like and dislike, inserting like and dislike rating action, counting likes and dislikes, delete row when unlike and undislike. 
Now, you can visit the index page without any issues.On the index page, if you click on any post title, you redirect to a single post page. Now, we will create this single post page. 
post.php

<?php require_once("config.php");
if(!isset($_SESSION['login_session'])){ 
	header("location:login.php");
}
else 
{
	$userid=$_SESSION['userid'];
    include("functions.php");
    $post_id=$_GET['id'];
}
?>
<!DOCTYPE html>
<?php 
  $sql="SELECT * FROM posts WHERE post_id=:post_id"; 
          $stmt=$db->prepare($sql);
          $stmt->bindParam(':post_id', $post_id ,PDO::PARAM_INT);
              $stmt->execute();
$row=$stmt->fetch();
$title=$row['title']; $content=$row['content']; $post_id=$row['post_id']; 
?>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>Like Dislike (Unlike) system in PHP and AJAX</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="style.css">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" />
<script src="like_dislike.js"></script>
</head>
<body>
<div class="container">
	<div div class="row">
	<div style="background:grey; color: #fff;" class="card">
	 	<h1><?php echo $title; ?></h1>	<a href="logout.php">Logout</a>
	</div>
</div>
<br>
    <div class="row">
<div class="col-sm-2"></div>
<div class="col-sm-8 list">
	  <div class="row card_item ">
	  	<div class="col-sm-12">
     <div class="content"><?php echo $content;?> </div> 
 </div>
 <div class="col-sm-12">
    <hr>
        <i <?php
         if(userLikesDislikes($post_id,$userid,'like',$db)): ?>
              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 getLikesDislikes($post_id,'like',$db); ?></span>
        
        &nbsp;&nbsp;&nbsp;&nbsp;
        <i 
          <?php if (userLikesDislikes($post_id,$userid,'dislike',$db)): ?>
              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 getLikesDislikes($post_id,'dislike',$db); ?></span>

 </div>

     </div>
 </div>
 <div class="col-sm-2"></div>
    </div>
</div>
</body>
</html>

In the above code, we have done the same thing as on the index page. Just fetch row data by id and display with like and dislike icons.This will be the same as Facebook and youtube single post pages.
As we already created like and dislike icons on the index and single post page, now we will create a JavaScript file. In this JS file, we will create AJAX code. When the user will click on the like or dislike button the AJAX will respond and execute the other PHP file where we will insert the post id, user id, and rating action (like and dislike) user_rating table. 
So let’s create a JS file. 
like_dislike.js

$(document).ready(function(){
$('.like-btn').on('click', function(){
   //$("#msg").html(data);
  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: 'rating_action.php',
    type: 'post',
    data: {
      'action': action,
      'post_id': post_id
    },
    success: function(data){
      //$("#msg").html(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: 'rating_action.php',
    type: 'post',
    data: {
      'action': action,
      'post_id': post_id
    },
    success: function(data){
          //$("#msg").html(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');
    }
  }); 

});

});

We already linked this JS file in an index file and a single post-PHP file. In the above code, we created a click event using jQuery.Ajax responds and sends the post id and action to the rating_action.php file and the rating_action.php file executes. 
We created the same for dislike and undislike in the same JS file. 
Now, we will create a rating_action.php file. 
In this file, we get and store the post id and action in variables also userid. We will insert the userid, post id, and action into user_rating file. 
We will return JSON encode data from this file using the getRating() user-defined function. We already created the getRating() function in the functions.php file. 
rating_action.php

<?php require_once("config.php");
include("functions.php");
if(isset($_SESSION['login_session'])){ 
	$userid=$_SESSION['userid'];
}
if(isset($_POST['action'])) {

  $postid = $_POST['post_id'];
  $action = $_POST['action'];
  switch ($action) {
  	case 'like':
    $vote_action='like';
insert_vote($userid,$postid,$vote_action,$db);
         break;
  	case 'dislike':
         $vote_action='dislike'; 
insert_vote($userid,$postid,$vote_action,$db);
         break;
  	case 'unlike':
delete_vote($userid,$postid,$db);

	      break;
  	case 'undislike':
  	delete_vote($userid,$postid,$db);
      break;
  	default:
  }
  // execute query to effect changes in the database ...
  echo getRating($postid,$db);
  exit(0);
}
?> 

In the above code, we created switch case statements to make more decisions. If the action is like then insert it into a database table or if the action is unlike then delete the row from the MYSQL database table. Follow the same for the dislike and undislike feature. 
If you want to make a logout feature then create a logout.php file. 
logout.php 

<?php require_once("config.php"); 
session_destroy(); 
header("location:login.php"); 
?>

You can log out using this logout.php file and log in with another user to like and dislike any post and check all likes count values and dislike count values on the right side of the like and dislike icons. 
In this way, you can create a like and dislike system in PHP and AJAX with the MYSQL database. 


Please Share

Recommended Posts:-