Creating Your Own Commenting System from Scratch

Creating Your Own Commenting System from Scratch

73 467935
Creating Your Own Commenting System from Scratch
How to create own commenting system

Own Commenting System with PHP and MySQL. Today I prepared new interesting article – I will tell how you can create own commenting system (AJAX) for your items (any units at your website) with PHP. For our demonstration – I prepared two SQL tables: first table will keep records of our items. It contain several fields: title, description, time of adding and comments count. Another table will keep records of comments. We will use jQuery too (for better interface behavior). One of features will spam protection (we can post no more than one comment every 10 minutes)!

Live Demo

[sociallocker]

download in package

[/sociallocker]


Now – download the source files and lets start coding !


Step 1. SQL

We will need to add 2 tables into our database:

CREATE TABLE IF NOT EXISTS `s163_items` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `title` varchar(255) default '',
  `description` text NOT NULL,
  `when` int(11) NOT NULL default '0',
  `comments_count` int(11) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `s163_items` (`title`, `description`, `when`, `comments_count`) VALUES
('Item #1', 'Here are you can put description of Item #1', UNIX_TIMESTAMP(), '0'),
('Item #2', 'Here are you can put description of Item #2', UNIX_TIMESTAMP()+1, '0'),
('Item #3', 'Here are you can put description of Item #3', UNIX_TIMESTAMP()+2, '0'),
('Item #4', 'Here are you can put description of Item #4', UNIX_TIMESTAMP()+3, '0'),
('Item #5', 'Here are you can put description of Item #5', UNIX_TIMESTAMP()+4, '0');
CREATE TABLE IF NOT EXISTS `s163_items_cmts` (
  `c_id` int(11) NOT NULL AUTO_INCREMENT ,
  `c_item_id` int(12) NOT NULL default '0',
  `c_ip` varchar(20) default NULL,
  `c_name` varchar(64) default '',
  `c_text` text NOT NULL ,
  `c_when` int(11) NOT NULL default '0',
  PRIMARY KEY (`c_id`),
  KEY `c_item_id` (`c_item_id`)
) ENGINE=MYISAM DEFAULT CHARSET=utf8;

This is simple tables: first for records of items, second one – for comments

Step 2. PHP

Here are source code of our main file:

index.php

<?php
// disabling possible warnings
if (version_compare(phpversion(), "5.3.0", ">=")  == 1)
  error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
else
  error_reporting(E_ALL & ~E_NOTICE);
require_once('classes/CMySQL.php'); // including service class to work with database
$sCode = '';
$iItemId = (int)$_GET['id'];
if ($iItemId) { // View item output
    $aItemInfo = $GLOBALS['MySQL']->getRow("SELECT * FROM `s163_items` WHERE `id` = '{$iItemId}'"); // getting info about item from database
    $sCode .= '<h1>'.$aItemInfo['title'].'</h1>';
    $sCode .= '<h3>'.date('F j, Y', $aItemInfo['when']).'</h3>';
    $sCode .= '<h2>Description:</h2>';
    $sCode .= '<h3>'.$aItemInfo['description'].'</h3>';
    $sCode .= '<h3><a href="'.$_SERVER['PHP_SELF'].'">back</a></h3>';
    // drawing last 5 comments
    $sComments = '';
    $aComments = $GLOBALS['MySQL']->getAll("SELECT * FROM `s163_items_cmts` WHERE `c_item_id` = '{$iItemId}' ORDER BY `c_when` DESC LIMIT 5");
    foreach ($aComments as $i => $aCmtsInfo) {
        $sWhen = date('F j, Y H:i', $aCmtsInfo['c_when']);
        $sComments .= <<<EOF
<div class="comment" id="{$aCmtsInfo['c_id']}">
    <p>Comment from {$aCmtsInfo['c_name']} <span>({$sWhen})</span>:</p>
    <p>{$aCmtsInfo['c_text']}</p>
</div>
EOF;
    }
    ob_start();
    ?>
    <div class="container" id="comments">
        <h2>Comments</h2>
        <script type="text/javascript">
        function submitComment(e) {
            var sName = $('#name').val();
            var sText = $('#text').val();
            if (sName && sText) {
                $.post('comment.php', { name: sName, text: sText, id: <?= $iItemId ?> },
                    function(data){
                        if (data != '1') {
                          $('#comments_list').fadeOut(1000, function () {
                            $(this).html(data);
                            $(this).fadeIn(1000);
                          });
                        } else {
                          $('#comments_warning2').fadeIn(1000, function () {
                            $(this).fadeOut(1000);
                          });
                        }
                    }
                );
            } else {
              $('#comments_warning1').fadeIn(1000, function () {
                $(this).fadeOut(1000);
              });
            }
        };
        </script>
        <div id="comments_warning1" style="display:none">Don`t forget to fill both fields (Name and Comment)</div>
        <div id="comments_warning2" style="display:none">You can post no more than one comment every 10 minutes (spam protection)</div>
        <form onsubmit="submitComment(this); return false;">
            <table>
                <tr><td class="label"><label>Your name: </label></td><td class="field"><input type="text" value="" title="Please enter your name" id="name" /></td></tr>
                <tr><td class="label"><label>Comment: </label></td><td class="field"><textarea name="text" id="text"></textarea></td></tr>
                <tr><td class="label">&nbsp;</td><td class="field"><input type="submit" value="Post comment" /></td></tr>
            </table>
        </form>
        <div id="comments_list"><?= $sComments ?></div>
    </div>
    <?
    $sCommentsBlock = ob_get_clean();
} else {
    $sCode .= '<h1>List of items:</h1>';
    $aItems = $GLOBALS['MySQL']->getAll("SELECT * FROM `s163_items` ORDER by `when` ASC"); // taking info about all items from database
    foreach ($aItems as $i => $aItemInfo) {
        $sCode .= '<h2><a href="'.$_SERVER['PHP_SELF'].'?id='.$aItemInfo['id'].'">'.$aItemInfo['title'].' item</a></h2>';
    }
}
?>
<!DOCTYPE html>
<html lang="en" >
    <head>
        <meta charset="utf-8" />
        <title>Creating own commenting system | Script Tutorials</title>
        <link href="css/main.css" rel="stylesheet" type="text/css" />
        <script type="text/javascript" src="js/jquery-1.5.2.min.js"></script>
    </head>
    <body>
        <div class="container">
            <?= $sCode ?>
        </div>
        <?= $sCommentsBlock ?>
        <footer>
            <h2>Creating own commenting system</h2>
            <a href="https://www.script-tutorials.com/how-to-create-own-commenting-system/" class="stuts">Back to original tutorial on <span>Script Tutorials</span></a>
        </footer>
    </body>
</html>

By default – this script will draw list of items. Each item have own page. All easy – we will display item title, time of adding (‘when’ field), description, and, most important – our new Comments block. This block contain form of adding new comments, and also will load us last 5 comments. I added my comments in most of places for better understanding. Ok, next PHP file is:

comment.php

<?php
// disabling possible warnings
if (version_compare(phpversion(), "5.3.0", ">=")  == 1)
  error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
else
  error_reporting(E_ALL & ~E_NOTICE);
require_once('classes/CMySQL.php'); // including service class to work with database
$iItemId = (int)$_POST['id']; // obtaining necessary information
$sIp = getVisitorIP();
$sName = $GLOBALS['MySQL']->escape(strip_tags($_POST['name']));
$sText = $GLOBALS['MySQL']->escape(strip_tags($_POST['text']));
if ($sName && $sText) {
    // checking - are you posted any comment recently or not?
    $iOldId = $GLOBALS['MySQL']->getOne("SELECT `c_item_id` FROM `s163_items_cmts` WHERE `c_item_id` = '{$iItemId}' AND `c_ip` = '{$sIp}' AND `c_when` >= UNIX_TIMESTAMP() - 600 LIMIT 1");
    if (! $iOldId) {
        // if all fine - allow to add comment
        $GLOBALS['MySQL']->res("INSERT INTO `s163_items_cmts` SET `c_item_id` = '{$iItemId}', `c_ip` = '{$sIp}', `c_when` = UNIX_TIMESTAMP(), `c_name` = '{$sName}', `c_text` = '{$sText}'");
        $GLOBALS['MySQL']->res("UPDATE `s163_items` SET `comments_count` = `comments_count` + 1 WHERE `id` = '{$iItemId}'");
        // and printing out last 5 comments
        $sOut = '';
        $aComments = $GLOBALS['MySQL']->getAll("SELECT * FROM `s163_items_cmts` WHERE `c_item_id` = '{$iItemId}' ORDER BY `c_when` DESC LIMIT 5");
        foreach ($aComments as $i => $aCmtsInfo) {
            $sWhen = date('F j, Y H:i', $aCmtsInfo['c_when']);
            $sOut .= <<<EOF
<div class="comment" id="{$aCmtsInfo['c_id']}">
    <p>Comment from {$aCmtsInfo['c_name']} <span>({$sWhen})</span>:</p>
    <p>{$aCmtsInfo['c_text']}</p>
</div>
EOF;
        }
        echo $sOut;
        exit;
    }
}
echo 1;
exit;
function getVisitorIP() {
    $ip = "0.0.0.0";
    if( ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) && ( !empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) ) {
        $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
    } elseif( ( isset( $_SERVER['HTTP_CLIENT_IP'])) && (!empty($_SERVER['HTTP_CLIENT_IP'] ) ) ) {
        $ip = explode(".",$_SERVER['HTTP_CLIENT_IP']);
        $ip = $ip[3].".".$ip[2].".".$ip[1].".".$ip[0];
    } elseif((!isset( $_SERVER['HTTP_X_FORWARDED_FOR'])) || (empty($_SERVER['HTTP_X_FORWARDED_FOR']))) {
        if ((!isset( $_SERVER['HTTP_CLIENT_IP'])) && (empty($_SERVER['HTTP_CLIENT_IP']))) {
            $ip = $_SERVER['REMOTE_ADDR'];
        }
    }
    return $ip;
}
?>

This file will accept POSTed comments and save them into database. In our project we have another one PHP file:

classes/CMySQL.php

This is service class to work with database prepared by me. This is nice class which you can use too. Database connection details located in this class in few variables, sure that you will able to configure this to your database. I don`t will publish its sources – this is not necessary for now. Available in package.

Step 3. JS

js/jquery-1.5.2.min.js

This is just jQuery library. Available in package.

Step 4. CSS

Now – all used CSS styles:

css/main.css

*{
    margin:0;
    padding:0;
}
body {
    background-repeat:no-repeat;
    background-color:#bababa;
    background-image: -webkit-radial-gradient(600px 200px, circle, #eee, #bababa 40%);
    background-image: -moz-radial-gradient(600px 200px, circle, #eee, #bababa 40%);
    background-image: -o-radial-gradient(600px 200px, circle, #eee, #bababa 40%);
    background-image: radial-gradient(600px 200px, circle, #eee, #bababa 40%);
    color:#fff;
    font:14px/1.3 Arial,sans-serif;
    min-height:600px;
}
footer {
    background-color:#212121;
    bottom:0;
    box-shadow: 0 -1px 2px #111111;
    display:block;
    height:70px;
    left:0;
    position:fixed;
    width:100%;
    z-index:100;
}
footer h2{
    font-size:22px;
    font-weight:normal;
    left:50%;
    margin-left:-400px;
    padding:22px 0;
    position:absolute;
    width:540px;
}
footer a.stuts,a.stuts:visited{
    border:none;
    text-decoration:none;
    color:#fcfcfc;
    font-size:14px;
    left:50%;
    line-height:31px;
    margin:23px 0 0 110px;
    position:absolute;
    top:0;
}
footer .stuts span {
    font-size:22px;
    font-weight:bold;
    margin-left:5px;
}
.container {
    border:3px #111 solid;
    color:#000;
    margin:20px auto;
    padding:15px;
    position:relative;
    text-align:center;
    width:500px;
    border-radius:15px;
    -moz-border-radius:15px;
    -webkit-border-radius:15px;
}
#comments form {
    background-color: rgba(255, 255, 255, 0.4);
    margin:10px 0;
    padding:10px;
    text-align:left;
}
#comments table td.label {
    color: #000;
    font-size: 13px;
    padding-right: 3px;
    text-align: right;
    width: 105px;
}
#comments table label {
    color: #000;
    font-size: 16px;
    font-weight: normal;
    vertical-align: middle;
}
#comments table td.field input, #comments table td.field textarea {
    border: 1px solid #96A6C5;
    font-family: Verdana,Arial,sans-serif;
    font-size: 16px;
    margin-top: 2px;
    padding: 6px;
    width: 250px;
}
#comments_list {
    background-color: rgba(255, 255, 255, 0.4);
    margin:10px 0;
    padding:10px;
    text-align:left;
}
#comments_list .comment {
    border-top:1px solid #000;
    padding:10px 0;
}
#comments_list .comment:first-child {
    border-top-width:0px;
}
#comments_list .comment span {
    font-size:11px;
}

Live Demo

Conclusion

Today we prepared great commenting system for your website. Sure that this material will be useful for your own projects. Good luck in your work!

SIMILAR ARTICLES

Design Patterns in PHP

0 114935

73 COMMENTS

  1. It’s all nice, but…

    What if i want to put a single comment on my web page? Not five of them. What part of a code to change and how.

  2. No, i mean if i want to use only one comment system, not to chose between 5 of “items” and comment one of them.

    • Ah, I see, then, separate our code into 2 parts, remove half (where I am working with all these items), and keep only most important – comments itself.
      And, hardcode as item id = 1 as example :-)

  3. When i looked in your code for the second time i realize that it could be used for much greater things then comments. When i’m finished, i will give you a link.

    Right now, i have a problem to insert a date into “when” with:
    $sql = mysql_query(“INSERT INTO `s163_items` (title, url, description, tagovi, when)
    VALUES(‘$title’,’$url’,’$opis’,’$tagovi’,UNIX_TIMESTAMP()”) or die (mysql_error())
    When is int(11), and that is main problem.

    • Hello Lord,
      Why? I didn’t add functionality to remove text from comment box after it send. You can add it of course, you can add
      $(‘#text’).val(”);
      directly after:
      $(this).html(data);
      $(this).fadeIn(1000);

  4. This is very nice example that you have shown to implement comment of yourself…:)

    But I want to ask one this, how to remove that limit of 10 minutes after posting one comment no other comment can be posted on that? I tried to look over that code but could not find.

    • Hello abhenav,
      In your case you should create a new one field to table with comments (s163_items_cmts) – ‘status’.
      It can be smallint field (we have to keep here 2 statuses – active and pending (or, 0 and 1)).
      Then, during adding new comments – set ‘pending’ status, finally – create some admin panel page to approve new (pending) comments.

  5. nice and awsome work admin , but i was fixed all and run it with my localhost , and i got empty page without items titles oO

  6. Hello sir I am getting the following errors

    Warning: mysql_connect() [function.mysql-connect]: Access denied for user ‘banksmok_a ‘@’localhost’ (using password: YES) in /home/banksmok/public_html/beauty/classes/CMySQL.php on line 19

    Warning: mysql_select_db(): supplied argument is not a valid MySQL-Link resource in /home/banksmok/public_html/beauty/classes/CMySQL.php on line 22

    Warning: mysql_query() [function.mysql-query]: Access denied for user ‘banksmok’@’localhost’ (using password: NO) in /home/banksmok/public_html/beauty/classes/CMySQL.php on line 24

    Warning: mysql_query() [function.mysql-query]: A link to the server could not be established in /home/banksmok/public_html/beauty/classes/CMySQL.php on line 24

    Warning: mysql_query(): supplied argument is not a valid MySQL-Link resource in /home/banksmok/public_html/beauty/classes/CMySQL.php on line 45
    Database query error

  7. this error Parse error: syntax error, unexpected $end in C:\xampp\htdocs\comenting\example163\index.php on line 108

  8. uhmm sorry for asking, i just have the same problem with bill it says Parse error: syntax error, unexpected $end in C:\wamp\www\example163\index.php on line 108. i did evrything. im just a newbie by the way, thanks!

    • Hi jinada,
      I’ve just rechecked demo on localhost, it works well. How do you run this demo? On localhost?
      In your case you should open it as: http://localhost/example163/index.php
      is it the same url you tried?

  9. Hello Sir, your design for comment box is excellent. I wanted just like this one.

    everything seems fine but when I run the file on my server i.e on localhost, it shows error of unexpected end of line in line 108. I saw from your comment replies that it shouldn’t contain $ on line 108 but there isn’t any symbol of $ in line 108. I went through the code 2 times but there isn’t anything like what the error shows.

    A help would be appreciated. Thank you!

  10. Hello , I like the UI part but i need only 1 text holder with submit button .
    I am implementing but the code looks like very complicated and complex .
    could you please sort the code …

    • Hello vikas,
      There are only two pretty small PHP files where you can make changes.
      If you want to remove ‘Your name’ field here, you can just search for ‘name’ in both files, and remove all located instances where it is used. It should be difficult.

  11. perfect tutorial but i have one question is this secure and how can add a a capacha like this one on you site

    thanks

    • The issue of security is up to you only.
      Right now it is safe about SQL injections. But if you are going to use it on your live website, yes, it would be useful to implement here extra protections (as example – a captcha, and maybe a protection of often submits, maybe something else). How exactly you can add a captcha? It depends only on a captcha you want to implement. They can have different realizations.

  12. Hi, I’m getting the same error when I try to access the example index.php file on localhost….Parse error: syntax error, unexpected end of file in C:\xampp\htdocs\commenting\example163\index.php on line 108. I can’t figure out how to fix it, any help would be much appreciated.

    • Hello Paul,
      Make sure that you use a proper PHP editor (I can recommend to use ‘Notepad++’), I think that you corrupted this file somehow, because there is no $ symbol on the line 108

  13. can u tell me how to show directly comments box not selection id
    and i need to put that form in some place of my html page

    • Hello shanmukh,
      Please clarify your question, what selection ID did you mention? You are welcome to use this form in any proper place on your website.

  14. hello admin,
    when running the localhost/example163/ index.php , it comes out with the error:
    “Parse error: syntax error, unexpected end of file in C:\xampp\htdocs\example163\index.php on line 108”

    Please what do i edit?

    • I can recommend also to check, if ‘short open tags’ is enabled on your localhost or now (this param should be ON)

    • Hello Aguja,
      Timezone? Hum, I think that you can use ‘date_default_timezone_set’ function to manage with time zones.

  15. Hi, i want to implement this comment feature on my web application that is built on java and uses jsp (MVC architecture). i am unable to include php code in jsp files. Is it possible ?? if not how to convert this php code to java. Else is there any other way to enable commenting feature.
    Thanks!

    • Hello Nishant,
      I am not sure if you can use PHP files as attachments for your Java project, I can recommend that you learn how to operate with database in java/jsp, and – to re-write both PHP files into jsp/java completely.

    • Hello Ferris, I already answered the same questions above, please read comments (you have to adjust settings for your database)

  16. I love your tut.. Just a question please. which file do i use, the index.php or comment.php?, as i noticed they are 2 different files

    • Hi Creig,
      You should use both files. As you see, the first one generates the main page, the second one is to extract comments for selected objects

  17. Actually i have a more complex question, I see where the items code is at and i see where there stored in data base, but how would i go about deleting the entire upper part where provides item number, date, description, and back link? so that it just shows the comment section on page?,, Thank you for any help, Creig

    • Hello Creig,
      If you want to change the generation of main elements, you can modify the index.php file. If you already have a list of your own objects, sure, you don’t need to draw it again, just omit it. Also, in the same file (index.php) there is a appropriate code that generates a single object page (with its comments)

    • Hello Aaron,
      Yes, this is possible. As I know, this is used when we have a question about scalability of the system.

    • Hello lidbary,
      In order to achieve your desire, you can expand the table with comments with another one field: parent_id (for instance). And, in case of replies – just save a parent comment ID in this field.

  18. Hi there
    Bravo and thanks for this wonderful script tutorial.
    I am trying to make few changed to suit what i wanted to do, but am a totally noob.
    I want to know this and couldn’t find answer any where.
    1- how to make users comments into a clickable links. ( example is user entered http://www.script-tutorials.com i wanted to be clickable )
    2 – how can make the comments box small like the name box? and limit the text.
    3- I wanted to make something that user can only post links and no gaps or space its for http,rtmp,mms etc. is this possible with this ?
    4 – finally add a category drop down to direct the text to the right category.
    I would really appreciate if any one can give me answer to this .
    thanks again for this tut.

    • Hi Ade,
      1. You will need to convert all links-look elements into links. You can do it in any order: before placing them into database, or when you display comments.
      2. You can achieve it with modifying of CSS styles.
      3. Yes, this is possible
      4. You will need to expand the comments table

  19. I try this with given url

    http://localhost/example163/index.php
    but i have an unexpected error message “Parse error: syntax error, unexpected $end in C:\xampp\htdocs\example163\index.php on line 107”

    pls help

  20. Hi Admin,

    Firstly, thanks for this awesome tutorial. I’m building a JSp Servlet based web application. I want to add comment facility in that. I’ve build a comment system just like you demonstrated. But now I want to add the “Reply” facility into it.

    You mentioned in a comment that another column can be added in to the comment dbase “parent_id”. Say, I’ve added it but can you plz tell me how these comments will be retrieved by AJAX (jQuery) when the page loads or user enters another comment.

    What I mean is that: comment then its reply then its reply then its reply, then another comment and its reply , then its reply and So On….

    How this chain can be achieved in MySQL ??

    Thanks in advance :-)

    • Hi Rahul,
      You described the nested comments functionality. And, as I explained earlier – it is possible to achieve. There are two possibilities:
      a) display nested (sub) comments on request (don’t display them initially)
      b) display nested comments automatically. In this case you will need to get all parents and childs, turn it into an array, and then parse this array building a nested html comments structure.

  21. Hello Deepak,
    I already explained this logic in details for Rahul, please check my reply.

  22. Good day admin, so tell where to alter the form to add to the comments and the comments themselves are displayed immediately to the id which is located.

    Sorry my english.
    translate by google :D

    • Hello Renskiy,
      What do you mean? To display comments on the main page (without opening single items) ?

  23. Hello
    Is there any way to have also pagination? I’m looking at a few hundred comments on a single page, can this be limited to just 10 comments per page, with multiple pages?

    • Hello Twisted,
      Of course you can, you are not restricted to expand the code in order to add the pagination into it. Does it represent a difficulty for you?

Leave a Reply