The Open Code Project

Creating a PHP/JSON/MySQL/JQuery Comment System (Updated)

January 17th,2010 by Allan Bogh

This is based on the original post entitled "Creating a PHP/MySQL/JSON Comment System".

Originally I had developed a PHP comment system based on the code from the Advanced Comment System sample from HotScripts. This code worked well, but it wasn't the most dynamic and needed to be improved.

I decided to use JQuery because it's simply the best framework that I've found to quickly make dynamic websites. There's no need for me to praise it since there are plenty of websites that do this already. For this article I will attempt to expand the code a little more and hopefully make it so you don't have to guess at what I'm doing.

The Comment Form

You will need several Javascript files and classes to make this page work properly. I've tried to include all necessary code so that you can paste this entire page to your website with minimal changes. You will have to modify how the comments are written, however. This is located in the foreach loop.

You will need the following:
JQuery (does some cool stuff)
striptags.js (makes the comment sane, but leaves <a> tags)
jqModal.css (some CSS for the modal dialog)
jqModal.js (displays the formatting/help information)
comments.js (code included below)
 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<link rel="stylesheet" type="text/css" href="css/Default/jqModal.css" />
<script type="text/javascript" src="js/striptags.js"></script>
<script type="text/javascript" src="js/jqModal.js"></script>

<script type="text/javascript">
    $().ready(function() {
        $('#dialog').jqm();
    });
</script>
</head>

<!-- print the comments -->
<div id="comments">

<?php
/*
 * You must include necessary classes to load comments or databases here.
 * For example:
 * include('config.inc.php') //creates database connection
 * include('article.php') //loads the article for this page as an object 
 */

$comments = $article->getComments(); //gets the comments array from the database

//output the title and count of comments
echo '<a name="comments"></a><h1>Comments ('.count($comments).')</h1><br />';

//write the comments, array positions come from the database column names
foreach($comments as $comment){
    echo '<p style="border-bottom:1px solid #000;">'.
         '<span style="float:right;">'.$comment['date_inserted'].'</span>'.
         '<span class="bold">'.$comment['authorname']."</span> ";
   
    //add the author website if they typed it in
    if($comment['authorwebsite'] != ""){
        echo '- <a href="'.$comment['authorwebsite'].'">'.
             $comment['authorwebsite'].'</a> ';
    }
    //HTML comments need newlines converted
    echo '<br />'.nl2br($comment['message']).'</p>';
}

?>
</div> <!-- end comments div -->

<!-- output the form to create a new comment -->
<div id="createcomment">

    <form action="commentform.php" method="post" onsubmit="(new Comments()).createComment(this);return false;">
        <input type="hidden" name="articleid" value="someidforyourarticle" />

        <label for="authorname" class="bold">Your name</label>:<br />
        <input type="text" id="authorname" name="authorname" title="Your name" onclick="this.style.backgroundColor='';" size="60" /><br />

        <label for="email" class="bold">Email (not used to contact you)</label>:<br />
        <input type="text" id="email" name="email" title="Email" onclick="this.style.backgroundColor='';" size="60" /><br />

        <label for="website">Website</label>:<br />
        <input type="text" id="website" size="60" name="website" /><br /><br />

        <label for="comment" class="bold">Comment</label>:
        <a href="javascript:void(0);" class="small jqModal">formatting help</a><br />

        <div class="jqmWindow" id="dialog">
            <a href="#" class="jqmClose">Close</a>
            <hr style="margin-top:5px;margin-bottom:5px;">
            <p class="bold">Formatting instructions:</p>
            <p>You can use &lt;a&gt; tags but everything else will be stripped and your comment will look funny.</p>
            <p>I swear, don't use html except the &lt;a&gt; tag or else some random star will supernova.
            Remember, we have a star right next to us, so don't try it.</p>
            <p>This isn't bbcode either so don't use it. That is all.</p>
        </div>

        <textarea id="comment" name="comment" title="Comment" onclick="this.style.backgroundColor='';" cols="60" rows="10"></textarea><br /><br />

        <input type="submit" name="submit" value="Create Comment" />

        <span class="green bold" id="wait" style="display:none;">Please wait while your comment is processed...</span>

    </form>

</div>
</body>
</html>



Comments JS Code (the JSON Helper)

The following code is an example of the JavaScript file that will handle new comment submissions. It sends the form information to a PHP page for processing on the database and then updates the webpage to display the new comment under the previous ones.

function Comments(){}


/**
 * updateView updates the webpage for the user to show the new 
 * comment. It uses the information that was submitted by the form
 * rather than the info from the database to save time.
 * The display should be exactly the same as if you refreshed the page.
 * If not, then there's a bug in the JS code.
 * @param response -1 signifies an error, anything else is OK
 * @param data - the oData property from the createComment function
 */
Comments.prototype.updateView = function(response,data){
    if(response != -1){
        var now = new Date();
        
        //formats the date to look like a MySQL date. 
        //Could be better but doesn't matter
        var formattedDate = now.getFullYear()+'-'+
            (now.getMonth()<10?'0'+now.getMonth():now.getMonth())+'-'+
            (now.getDate()<10?'0'+now.getDate():now.getDate())+' '+
            (now.getHours()<10?'0'+now.getHours():now.getHours())+':'+
            (now.getMinutes()<10?'0'+now.getMinutes():now.getMinutes())+':'+
            (now.getSeconds()<10?'0'+now.getSeconds():now.getSeconds());
        
        //formats the comment to preserve newlines but eliminate HTML 
        //(it just displays the characters)
        var safeComment = strip_tags(data.comment.replace(/\n/g,'[newline]'),"<a>").replace(/\[newline\]/g,'<br />');

        //prepares the comment information
        var html = '<p style="border-bottom:1px solid #000;"><span style="float:right;">'+formattedDate+'</span>'+
                    '<span class="bold">'+data.authorname+"</span> "+
                    (data.authorwebsite!=""?'- <a href="'+data.authorwebsite+'">'+data.authorwebsite+'</a> ':'')+
                    '<br />'+safeComment+'</p>';

        //hide the wait message
        $("#wait").hide();
        //append the comment to the comments list
        $("#comments").append(html);
    }else{ //an error occurred
        //hide the wait div
        $("#wait").hide();
        alert("There was a problem inserting your comment.");
    }
};
/**
 * createComment sends the comment information to the server
 * using JSON. It will call updateView when it's finished.
 * @param form - the form that contains the comment elements.
 *               the elements must be named: articleid, authorid,
 *               authorname, email, website, and comment
 */
Comments.prototype.createComment = function(form){
    //these are the required fields
    var requiredFields = new Array(form.authorname,form.email,form.comment);
    
    //check required text fields, don't process if they're blank
    if(!checkRequiredTextFields(requiredFields)){
        return;
    }

    //define the data
    var oData = {
                    requesting: "Comment",
                    articleid:form.articleid.value,
                    authorname:form.authorname.value,
                    authoremail:form.email.value,
                    authorwebsite:form.website.value,
                    comment: form.comment.value
                };
    //show the wait message
    $("#wait").show();

    //send the comment to the server
    $.post("/ajax/comment.php",oData,function(responseText){(new Comments).updateView(responseText,oData);},"text");
};



Submitting Comments to the Database

This PHP code will submit the comment to a database. The database connection must already be established, I would do this in the config file. The file will clean the comment and all fields to prevent unwanted HTML, JavaScript code, or MySQL injection attacks from occurring. You'll notice that it leaves hyperlinks alone. This is intentional, as these are allowed to be displayed in the comments.

<?php

//include certain required files
require("../includes/config.inc.php");

if(isset($_POST)){ //

    header("Content-Type: text/plain; charset=UTF-8");

    $oData = $_POST;

    switch($oData["requesting"]){
        case "Comment": //someday there could be other cases
            //check the required fields again
            if(strlen($oData["comment"]) > 0 && 
                strlen($oData["authorname"]) > 0 && 
                strlen($oData["authoremail"]) > 0)
            {
                //sanitize the data
                $oData["comment"] = mysql_real_escape_string(strip_tags($oData["comment"],'<a>'));
                $oData["authorname"] = mysql_real_escape_string(htmlspecialchars($oData["authorname"]));
                $oData["website"] = mysql_real_escape_string($oData["authorwebsite"]);
                $oData["authoremail"] = mysql_real_escape_string($oData["authoremail"]);

                //insert comment into system
                mysql_query("INSERT INTO advanced_comment_system ".
                            "(date_inserted,article,message,".
                            "authorname,authoremail,authorwebsite,ip) ".
                            "VALUES (NOW(),'{$oData["articleid"]}',".
                                     "'{$oData["comment"]}',".
                                     "'{$oData["authorname"]}',".
                                     "'{$oData["authoremail"]}',".
                                     ($oData["authorwebsite"]==''?"NULL":"'{$oData["authorwebsite"]}'").",".
                                     "'{$_SERVER['REMOTE_ADDR']}'".")",$dbconn)
                $theId = mysql_insert_id($dbconn);

                echo json_encode($theId);
            }else{ //the required fields weren't met
                echo json_encode(-1);
            }
        break;
    }
}else{ //nothing to do
    header("Location: http://www.opencodeproject.com");
    die(); //make sure it doesn't process the rest of the page.
}
?>


The Database

The database table is fairly basic and doesn't require any relationships besides the one to the article or webpage. You may modify this to your own ends. It's based on the Advanced Comment System database and in my code above I specifically use the `advanced_comment_system` table. 

Comment System database schema
Field Type Null Default Extra
id int(10) No   auto_increment
date_inserted datetime No    
article int(11) No    
message text No    
authorname varchar(64) No    
authoremail varchar(128) No    
authorwebsite varchar(128) Yes NULL  
ip varchar(24) No    

The create table SQL code is included below.

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";

-- --------------------------------------------------------

--
-- Table structure for table `advanced_comment_system`
--

CREATE TABLE IF NOT EXISTS `advanced_comment_system` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `date_inserted` datetime NOT NULL,
  `article` int(11) NOT NULL,
  `message` text NOT NULL,
  `authorname` varchar(64) NOT NULL,
  `authoremail` varchar(128) NOT NULL,
  `authorwebsite` varchar(128) default NULL,
  `ip` varchar(24) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;


Conclusion

With the code and information that I provided above, you should have the means to create your own comment system. You will have to modify the code to your own ends to make it look  and work like you want it to. You may also want to include additional features and safeties. In my personal code I've included article following and comment deletion. You may want to include Captcha or hidden text fields for bot prevention.

If you see any mistakes please feel free to leave a comment. I will gladly provide any information or support that I can offer. Good luck on your new comment systems.

Comments (1)


2010-01-18 07:48:47Ronald Nicholls - http://www.boxofficebuz.net
Great tutorial, i am working on putting this into my own site.

:

:

:


: formatting help
Close

Formatting instructions:

You can use <a> tags but everything else will be stripped and your comment will look funny.

I swear, don't use html except the <a> tag or else some random star will supernova. Remember, we have a star right next to us, so don't try it.

This isn't bbcode either so don't use it. That is all.