Creating a PHP/MySQL/JSON Comment System

Written by:
Published on

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>
<html>

<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>'.$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">Your name</label>:<br />
        <input type="text" id="authorname" name="authorname" title="Your name" onclick="this.style.backgroundColor='';" size="60" /><br />

        <label for="email">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">Comment</label>:
        <a href="javascript:void(0);">formatting help</a><br />

        <div id="dialog">
            <a href="#">Close</a>
            <hr style="margin-top:5px;margin-bottom:5px;">
            <p>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 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>'+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.

This entry was posted in Javascript, JQuery, MySQL, PHP and tagged , , , by Allan Bogh. Bookmark the permalink.
Allan Bogh

About Allan Bogh

I'm an Active Directory consultant, programmer, web developer, database developer, and tinkerer. I am also the administrator of The Open Code Project. I created and moderate r/ActiveDirectory and, am the primary developer of Reddit Uppers and Downers Enhanced (a part of RES). I also have a love of robotics, working with the Arduino platform.

Sample Projects:

  • ImgAlbum - ImgAlbum is a picture album website that includes speedy image delivery using custom GD2 PHP code and folder/subfolder traversal. Other album websites such as Picasa don't include sub-albums or subfolder uploads, so I am developing my own system where a user can upload an entire folder structure full of images and the system will automatically process the images to create albums.
  • Reddit Uppers and Downers Enhanced - Lead developer, improved speed significantly, incorporated other developers' additions with attribution, project is a part of RES and is used by tens of thousands of people every day.
  • RE/Max Properties website - Created MLS replication system, pulling NWMLS XML records using PHP. Created a Google Maps interface to display NWMLS results on the website (no longer in use). Before leaving I created a home value calculator based on the MLS data and make the website into a template system for agents.
  • Stealth Media Solutions - A website and graphic design company that I used to work for. The website was designed by our designer, I implemented the code with rudimentary means compared to the frameworks available today.
  • Photography Plus - Another design of Stealth Media Solutions. This website includes a WYSIWYG editor for the owner to modify pages. It uses PHP, and Flash.
  • Highpointe Church - Flash PoC. Highpointe Church wanted a proof of concept design from Stealth Media Solutions. Our designer made it and I created the webpage in Flash. The customer was very specific about using Flash, although it may not have been the most flexible choice. Custom javascript was developed to resize the background image dynamically (worked best in Firefox and IE).

Leave a Reply

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

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>