4 Steps Simple Like Dislike System In PHP MySQL

Welcome to a tutorial on how to build a simple like and dislike rating system with PHP and MySQL. Social media is big these days and I am sure you have already seen “upvote”, “downvote”, “like”, and “dislike” features everywhere on Facebook, YouTube, Twitter, and more. Well, if you want to create your own independent like/dislikes system, it really isn’t that difficult.

A basic like/dislike system only requires a couple of key components:

  • A database table to store the user’s likes and dislikes.
  • A PHP library and AJAX handler to manage the likes and dislikes.
  • Lastly, implementation onto the pages themselves.

Let us walk through an actual example in this guide – Read on!

ⓘ I have included a zip file with all the source code at the start of this tutorial, so you don’t have to copy-paste everything… Or if you just want to dive straight in.

 

 

TABLE OF CONTENTS

Download & Notes Like Dislike Useful Bits & Links
The End

 

DOWNLOAD & NOTES

Firstly, here is the download link to the example code as promised.

 

QUICK NOTES

  • Create a database and import 1-database.sql.
  • Change the database settings in 2-reactions.php to your own.
  • Launch 3-page.php in your browser.
If you spot a bug, feel free to comment below. I try to answer short questions too, but it is one person versus the entire world… If you need answers urgently, please check out my list of websites to get help with programming.

 

 

EXAMPLE CODE DOWNLOAD

Click here to download the source code, I have released it under the MIT license, so feel free to build on top of it or use it in your own project.

 

 

LIKE DISLIKE SYSTEM

All right, let us now get into the details of building a like dislike system with PHP and MYSQL.

 

STEP 1) REACTIONS DATABASE TABLE

1-database.sql
CREATE TABLE `reactions` (
  `id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL,
  `reaction` tinyint(1) NOT NULL DEFAULT '1'
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

ALTER TABLE `reactions`
  ADD PRIMARY KEY (`id`,`user_id`),
  ADD KEY `reaction` (`reaction`);
Field Description
id Primary and foreign key. The post ID, product ID, video ID – Whatever you want to add a like/dislike button to.
user_id Primary and foreign key. The user who liked/disliked.
reaction For this example, we will use -1 for dislike and 1 for like.

Yep, 3 fields are actually all we need to record the likes and dislikes.

 

 

STEP 2) PHP REACTIONS LIBRARY

2-reactions.php
<?php
class Reactions {
  // (A) CONSTRUCTOR - CONNECT TO DATABASE
  private $pdo;
  private $stmt;
  public $error;
  function __construct () {
    try {
      $this->pdo = new PDO(
        "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=" . DB_CHARSET,
        DB_USER, DB_PASSWORD, [
          PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
          PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_NAMED
        ]
      );
    } catch (Exception $ex) { exit($ex->getMessage()); }
  }

  // (B) DESTRUCTOR - CLOSE DATABASE CONNECTION
  function __destruct () {
    $this->pdo = null;
    $this->stmt = null;
  }

  // (C) GET REACTIONS FOR ID
  function get ($id, $uid=null) {
    // (C1) GET TOTAL REACTIONS
    $results = ["react" => [0, 0]]; // [LIKES, DISLIKES]
    $this->stmt = $this->pdo->prepare(
      "SELECT `reaction`, COUNT(`reaction`) `total`
      FROM `reactions` WHERE `id`=?
      GROUP BY `reaction`"
    );
    $this->stmt->execute([$id]);
    while ($row = $this->stmt->fetch()) {
      if ($row["reaction"]==1) { $results["react"][0] = $row["total"]; }
      else { $results["react"][1] = $row["total"]; }
    }

    // (C2) GET REACTION BY USER (IF SPECIFIED)
    if ($uid !== null) {
      $this->stmt = $this->pdo->prepare(
        "SELECT `reaction` FROM `reactions` WHERE `id`=? AND `user_id`=?"
      );
      $this->stmt->execute([$id, $uid]);
      $results["user"] = $this->stmt->fetchColumn();
    }
    return $results;
  }
 
  // (D) SAVE REACTION
  function save ($id, $uid, $react) {
    // (D1) FORMULATE SQL
    if ($react == 0) {
      $sql = "DELETE FROM `reactions` WHERE `id`=? AND `user_id`=?";
      $data = [$id, $uid];
    } else {
      $sql = "REPLACE INTO `reactions` (`id`, `user_id`, `reaction`) VALUES (?,?,?)";
      $data = [$id, $uid, $react];
    }
 
    // (D2) EXECUTE SQL
    try {
      $this->stmt = $this->pdo->prepare($sql);
      $this->stmt->execute($data);
      return true;
    } catch (Exception $ex) {
      $this->error = $ex->getMessage();
      return false;
    }
  }
}

// (E) DATABASE SETTINGS - CHANGE TO YOUR OWN!
define("DB_HOST", "localhost");
define("DB_NAME", "test");
define("DB_CHARSET", "utf8");
define("DB_USER", "root");
define("DB_PASSWORD", "");

// (F) CREATE NEW CONTENT OBJECT
$_REACT = new Reactions();

This one looks massive at first, but keep calm and look carefully.

  • (A & B) On creating a $REACT = new Reactions() object, the constructor will automatically connect to the database. The destructor closes the connection.
  • (C & D) There are only 2 core functions!
    • function get() Gets the total number of reactions (likes and dislikes) for the given post/video/product ID. If the user ID is provided, it will also get the user’s reaction.
    • function save() Self-explanatory, save a user’s reaction. Set $react = 0 to remove the user’s reaction.
  • (E & F) The database settings, and creating a new Reactions() object. Doh.

 

 

STEP 3) DUMMY PRODUCT PAGE

THE HTML

3-demo.php
<!-- (A) LOAD LIKE/DISLIKE BUTTON -->
<link rel="stylesheet" href="lidi.css"/>
<script src="lidi.js"></script>

<!-- (B) RENDER LIKE/DISLIKE BUTTON HERE -->
<div id="demowrap">
  <img src="raspberry.jpg"/>
  <div id="demo"></div>
</div>

The only important part here is using <div id="demo"> to generate the like/dislike button. Also, lidi.js and lidi.css is a like/dislike button plugin that I created. Shall leave a link below if you are interested to learn more.

 

THE PHP/JAVASCRIPT

3-demo.php
<!-- (C) PHP GET REACTIONS -->
<?php
require "2-reactions.php";
$id = 900; // POST/PRODUCT/WHATEVER ID
$uid = 1; // USER ID, USE $_SESSION IN YOUR PROJECT
$reacts = $_REACT->get($id, $uid);
?>
 
<!-- (D) GENERATE LIKE/DISLIKE BUTTON -->
<script>
lidi.create({
  // (D1) LIKE/DISLIKE BUTTON SETTINGS
  hWrap : document.getElementById("demo"),
  status : <?=$reacts["user"]?>,
  count : [<?=$reacts["react"][0]?>, <?=$reacts["react"][1]?>],
 
  // (D2) UPDATE SERVER ON REACTION CHANGE
  onChange : (status, recount) => {
    // FORM DATA
    var data = new FormData();
    data.append("id", <?=$id?>);
    data.append("react", status);
 
    // FETCH
    fetch("4-ajax.php", { method: "POST", body: data })
    .then(res => res.json())
    .then((res) => {
      if (res.error) { alert(res.error); }
      else { recount(res); }
    })
    .catch((err) => { console.error(err); });
  }
});
</script>
  • (C) Use the PHP library to get the likes and dislikes of this product. Of course, the user ID and product ID are fixed for this example… Adopt the IDs from the session, get, or post vars in your own project.
  • (D) Then, we “weave” the details into Javascript to generate the button itself. Take note of onChange here. When the user clicks on the button, this will fire a fetch request to the server to update the like/dislike status. The server will then return with an updated count.

 

 

STEP 4) REACTIONS AJAX HANDLER

4-ajax.php
<?php
// (A) INIT
require "2-reactions.php";
$uid = 1; // USER ID, USE $_SESSION IN YOUR PROJECT
 
// (B) SAVE/UPDATE REACTION
if (!$_REACT->save($_POST["id"], $uid, $_POST["react"])) {
  exit(json_encode(["error" => $_REACT->error]));
}
 
// (C) GET UPDATED REACTIONS
$result = $_REACT->get($_POST["id"]);
echo json_encode($result["react"]);

The last step. An AJAX handler to update the like/dislike status, then return with the updated count.

 

 

USEFUL BITS & LINKS

That’s all for the code, and here are a few small extras that may be useful to you.

 

LINKS & REFERENCES

 

THE END

Thank you for reading, and we have come to the end of this guide. I hope that it has helped you to improve your project, and if you want to share anything with this guide, please feel free to comment below. Good luck and happy coding!

12 thoughts on “4 Steps Simple Like Dislike System In PHP MySQL”

  1. Dear Mr. Toh, thank you so much for your tutorials and all the stuff. And also for your wise words in the help and FAQs. Could you (or someone else) please recommend me a site to learn about the $_SESSION for using it in my own project (I’m an absolute beginner but could understand all this up to here)? Is there a way to donate? Many thanks and best wishes from Germany! Andreas

    1. The long learning process for absolute beginners to fully understand:

      1) Start with cookies – https://code-boxx.com/cookies-in-php/
      2) Then, PHP sessions (sessions are built on top of cookies) – https://code-boxx.com/sessions-in-php/
      3) If you are not familiar with OOP, just about PHP OOP tutorial on the Internet – https://www.google.com/search?q=php+oop+tutorial
      4) Working with MySQL database in PHP – https://www.google.com/search?q=php+mysql+pdo+tutorial
      5) Javascript AJAX FETCH – https://www.digitalocean.com/community/tutorials/how-to-use-the-javascript-fetch-api-to-get-data
      6) A simple user login system (the part on user ID, to track user likes and dislikes) – https://code-boxx.com/simple-login-php-mysql/
      7) Or another way to track users without session using JSON Web Tokens (JWT) – https://code-boxx.com/jwt-login-authentication-php-mysql/

      1. Many thanks! I already started to learn php from the beginning. It is quiet interesting and I will see whether an old man can learn it any more 😆. I already have installed the great script SITELOCK for users login (like on my page). Maybe I can use this in combination with your code. Ich will try to find out. All the best for you, Mr. Toh, and again: Is there a way to donate (for you)?!

        Best wishes for 2022 from Germany! Andreas

      1. No problems here with Chrome, Opera, Edge, and Firefox – Not sure which version of Firefox you are using… Your customizations probably broke it.

Leave a Comment

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