4 Steps Simple Comment System With PHP MYSQL AJAX

Welcome to a tutorial on how to create a simple comment system using PHP, MYSQL, and AJAX. Want to upgrade your website or eCommerce store? Allow users to enter comments on a post or product? Well, it really isn’t too difficult to create a comment (or feedback) system from scratch – Let us walk through a simple one 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 Comments System 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-comments.sql.
  • Change the database settings to your own in 2-ajax-comments.php.
  • Launch 3a-comments.html in your web browser, a friendly reminder to use http:// and not file://.
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.

 

 

SOURCE CODE DOWNLOAD

Click here to download all the example 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.

 

 

PHP MYSQL COMMENTS SYSTEM

All right, let us now get into the steps of creating an easy AJAX-driven comments system with PHP and MYSQL.

 

STEP 1) COMMENTS DATABASE TABLE

1-comments.sql
CREATE TABLE `comments` (
  `comment_id` int(11) NOT NULL,
  `post_id` int(11) NOT NULL,
  `timestamp` datetime NOT NULL DEFAULT current_timestamp(),
  `name` varchar(255) NOT NULL,
  `message` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `comments`
  ADD PRIMARY KEY (`comment_id`);

ALTER TABLE `comments`
  MODIFY `comment_id` int(11) NOT NULL AUTO_INCREMENT;
Field Description
comment_id Primary key and auto-increment.
post_id Foreign key. Use this to identify which comments belong to which post (or product).
timestamp Date and time when the comment is posted.
name Name of the user.
message Comment message.

This should be easy enough, but you might want to change the structure a little to fit your own project. For example, it may make sense to add an email field, or use URL slugs instead of ID (change post_id to post_slug, use VARCHAR instead of INT).

 

 

STEP 2) PHP COMMENT AJAX HANDLER

2-ajax-comments.php
<?php
// (A) CONNECT TO DATABASE - CHANGE SETTINGS TO YOUR OWN !
$dbhost = "localhost";
$dbname = "test";
$dbchar = "utf8";
$dbuser = "root";
$dbpass = "";
try {
  $pdo = new PDO(
    "mysql:host=$dbhost;dbname=$dbname;charset=$dbchar",
    $dbuser, $dbpass, [
      PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
      PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_NAMED
    ]
  );
} catch (Exception $ex) { exit($ex->getMessage()); }

if ($_POST["req"]) { switch ($_POST["req"]) {
  // (B) INVALID REQUEST
  default: echo "Invalid request"; break;
 
  // (C) SHOW COMMENTS
  case "show";
    $stmt = $pdo->prepare("SELECT `name`, `timestamp`, `message` FROM `comments` WHERE `post_id`=? ORDER BY `timestamp` ASC");
    $stmt->execute([$_POST["pid"]]);
    while ($r = $stmt->fetch()) { ?>
    <div class="crow">
      <div class="chead">
        <div class="cname"><?=$r["name"]?></div>
        <div class="ctime">[<?=$r["timestamp"]?>]</div>
      </div>
      <div class="cmsg"><?=$r["message"]?></div>
    </div>
    <?php }
    break;
 
  // (D) ADD COMMENT
  case "add":
    // (D1) CHECKS
    if (!isset($_POST["pid"]) || !isset($_POST["name"]) || !isset($_POST["msg"])) {
      exit("Please provide the Post ID, name, and message");
    }

    // (D2) INSERT
    try {
      $stmt = $pdo->prepare("INSERT INTO `comments` (`post_id`, `name`, `message`) VALUES (?,?,?)");
      $stmt->execute([$_POST["pid"], htmlentities($_POST["name"]), htmlentities($_POST["msg"])]);
    } catch (Exception $ex) { exit($ex->getMessage()); }
    echo "OK";
    break;
}}

// (E) CLOSE DATABASE CONNECTION
$stmt = null;
$pdo = null;

This may look complicated at first, but keep calm and look carefully. How this AJAX handler works is very simple, just post the request followed by the required parameters:

  • To show the comments – $_POST = ["req"=>"show", "pid"=>888]
  • To add a comment – $_POST = ["req"=>"add", "pid"=>888, "name"=>"John", "msg"=>"Hello"]

P.S. Remember to change the database settings to your own.

 

 

STEP 3) HTML COMMENTS PAGE

3a-comments.html
<!-- (A) JS + CSS -->
<script src="3b-comments.js"></script>
<link href="3c-comments.css" rel="stylesheet">
 
<!-- (B) GIVE THIS PAGE A HIDDEN POST ID -->
<input type="hidden" id="pid" value="999"/>
 
<!-- (C) COMMENTS WILL LOAD HERE -->
<h1>COMMENTS</h1>
<div id="cwrap"></div>
 
<!-- (D) ADD NEW COMMENT -->
<form id="cadd" onsubmit="return comments.add(this)">
  <h1>Leave a reply</h1>
  <input type="text" id="cname" placeholder="Name" required/>
  <textarea id="cmsg" placeholder="Message" required></textarea>
  <input type="submit" value="Post Comment"/>
</form>

The HTML itself is very straightforward, but please make sure that your comments page has the following:

  1. Include the comments Javascript on the page. Doh.
  2. Tag the page with a unique ID, place it into a hidden field – <input type="hidden" id="pid" value="X"/>.
  3. Create a container to load all the comments – <div id="cwrap">.
  4. Finally, the “Add A Comment” form itself – <form id="cadd">.

 

 

STEP 4) COMMENTS JAVASCRIPT

3b-comments.js
var comments = {
  // (A) AJAX HELPER FUNCTION
  ajax : (data, after) => {
    // (A1) DATA TO SEND
    var fdata = new FormData();
    fdata.append("pid", document.getElementById("pid").value);
    for (let k in data) { fdata.append(k, data[k]); }
 
    // (A2) AJAX FETCH
    fetch("2-ajax-comments.php", { method: "POST", body: fdata })
    .then(res => res.text()).then(after)
    .catch((err) => { console.error(err); });
  },
  
  // (B) LOAD COMMENTS INTO <DIV ID="CWRAP">
  load : () => {
    comments.ajax(
      { req: "show" }, 
      (res) => { document.getElementById("cwrap").innerHTML = res; }
    );
  },
  
  // (C) ADD COMMENT
  add: () => {
    comments.ajax(
      // (C1) DATA TO SEND
      {
        req : "add",
        name : document.getElementById("cname").value,
        msg : document.getElementById("cmsg").value
      },
      
      // (C2) RELOAD COMMENTS + RESET FORM AFTER ADD
      (res) => {
        if (tres == "OK") {
          document.getElementById("cadd").reset();
          comments.load();
        } else { alert(res); }
      }
    );
    return false;
  }
};
window.addEventListener("DOMContentLoaded", comments.load);

Some beginners may panic at the sight of Javascript, but it is actually simple and straightforward again.

  1. We will be using AJAX to drive the comments, and thus the need for this comments.ajax() helper function. Yep, all it does is nicely formulate the data and send out an AJAX request to the server-side 2-ajax-comments.php.
  2. On window load, comments.load() will fire up. As you can guess, this does an AJAX call to the server to load the comments for the current page.
  3. The comments.add() function is fired when the user adds a new comment. Again, this is AJAX-driven.

 

 

USEFUL BITS & LINKS

We are finally done with the entire system, and here are some extras that may be useful to you.

 

ANTI-SPAM

Need some spam protection? Check out Google reCAPTCHA – It’s free. Here’s an example of reCaptcha with a contact form if you are interested.

 

SORT COMMENTS IN ASCENDING OR DESCENDING ORDER

2-ajax-comments.php
// (C) SHOW COMMENTS
ORDER BY `timestamp` ASC
ORDER BY `timestamp` DESC

 

MANUAL APPROVAL

Want to further fight spam? Manually approve and moderate the comments? First, you are going to need an additional “approved” flag in the comments table:

ALTER TABLE `comments` 
ADD `approved` TINYINT(1) NOT NULL DEFAULT '0' 
AFTER `message`, ADD INDEX (`approved`);

Then change the SQL to show only approved comments:

2-ajax-comments.php
SELECT `name`, `timestamp`, `message`
FROM `comments` 
WHERE `post_id`=? AND `approved`=1 
ORDER BY `timestamp` ASC

Of course, don’t forget that you will need to manually approve the comments.

UPDATE `comments`
SET `approved`=1 
WHERE `comment_id`=?

 

ONLY REGISTERED USERS CAN COMMENT

First off, you need to have a user/login system in place. I will leave a link below to another tutorial if you want to follow up. Start the session, and show the “add comment” form only if the user is signed in.

3a-comments.php
<?php 
// START SESSION
session_start();

// ADD COMMENT - ONLY FOR REGISTERED USERS
if (is_array($_SESSION["user"])) { ?>
<form id="cadd" onsubmit="return comments.add(this)">
  ...
</form>
<?php }

For further protection, also restrict the PHP AJAX handler.

2-ajax-comments.php
<?php
case "add":
  if (is_array($_SESSION["user"])) {
    // INSERT INTO ...
  }
  break;

 

EXTRA LINKS

 

THE END

Thank you for reading, and we have come to the end of this guide. I hope it has given you a quick boost to your project, but remember that this is ultimately only the first step. This simple comment system is only a skeleton – It lacks moderation, anti-spam, security, administration, and some of your own customizations.

But with some work, I am sure you can turn this into a pretty good one. If there are things that you like to add to this guide, please feel free to comment below. Good luck and happy coding!

77 thoughts on “4 Steps Simple Comment System With PHP MYSQL AJAX”

  1. WS: Nonsensical, irrelevant, for comic relief only (also to piss the spammers off). NON-SPONSORED SPAM POST BROUGHT TO YOU BY PAK CHOI HOSTING CO.

    Pak Choi is a vegetable company based in Pakistan, with farms in Europe and LALAland (TM). We provide web hosting services and Pak Choi for different types of websites including corporate, personal, and e-commerce sites.

    Most importantly, we don’t have a budget to pay for proper advertising and marketing, so we abuse our staff to spam blog comments all day instead. Customers can expect “excellent” services from our professional spammers who also double up as untrained tech support! Pay peanuts, get monkeys! Great deal!

    Age tea tea peace slash pak ch amp dot com slash shame the spammers.

  2. EDIT : MULTIPLE COMMENTS COMBINED

    (A) In sql file: int() should have no arguments – int. utf8 should be utf8mb4.
    Add path to folder if different when adding to :
    Changed to for Comments title. CSS: h4 { font-size: 16px; margin: 0 0 1px 0; text-transform: uppercase; color: #4660E2 }
    Changed to for Reply title. CSS: h5 { font-size: 16px; margin: 0 0 1px 0; text-transform: uppercase; color: #000000 }
    Add path to 3b-comments.js if needed: fetch(“comments-php/2-ajax-comments.php”,
    Global POST command should be filtered: Example: if ($_POST[“req”]) { switch ($_POST[“req”]) { should be: if (filter_input(INPUT_POST, ‘req’)) { switch (filter_input(INPUT_POST, ‘req’)) {
    HOWEVER, some updates caused the comment system to fail. Maybe you could figure this one out for the three lines of code affected in 2-ajax-comments.php?
    Otherwise, works great! Thanks.

    (B) Where do you place the response for moderation? “Your comment is awaiting moderation.” works great here.
    My page takes the comment, then resets the window without saying anything. Thanks.

    (C) I’m getting to where I really like this simple comment system. But I’m with Pankaj. I really need at least one level reply to make this comment system almost perfect.

    We can all see it works here…how about some code snippets and a few pointers to let us really try to do it?

    And where is your donate button? ;->

    1. (A1) Both UTF8 and UFT8MB4 work. One supports 3 bytes characters, the other supports 4 bytes. Initially used UTF8(MB3) for backward compatibility, will update the tutorial in due time as the world has moved forward to support mb4.
      (A2) No point validating the request. If it is invalid, the AJAX handler simply returns an “invalid request”.
      (B) As above, “MANUAL APPROVAL”.
      (C) As mentioned, it involves recursion and is not simple.

      Good luck with your project.
      https://code-boxx.com/faq/#help “Requests for new features may be considered, but will not be immediately answered.”

  3. Hello, I’m really get help by your amazing tutorial, but I got confused about how to delete the comment by the user. I already try to get the comment_id column and make changes in the comment.js but the $r[‘comment_id]; always filled with the oldest comment id that posted by the user. When I echo that it generates the exact comment_id but when it brings to the js file and back to the ajax-comment.php its value is back to the oldest comment id that posted by the user. I’m sorry if my explanation is confusing but I hope you understand and can give me some advice. Thanks in advance!

  4. Hi, thanks for this very useful source.
    But I want to ask is how to reverse data from mysql.
    That means I want the latest comment to appear first.
    Thank you very much!!!

    1. SORT COMMENTS IN ASCENDING OR DESCENDING ORDER
      2-ajax-comments.php
      // (C) SHOW COMMENTS
      ORDER BY `timestamp` ASC
      ORDER BY `timestamp` DESC

Leave a Comment

Your email address will not be published.