Johan Broddfelt
/* Comments on code */

Give your audience a voice

There are several reasons why you would like a way for your viewers to comment on your site. The first is feedback. The reason why you write about things is because you want feedback. Or at least I do. I know that I'm not the best, nor do I know it all. So it is really nice to hear you opinion on my way of thinking about code. Because then I can learn from it and I might be able to explain myself in a better way, if I disagree with your opinion.
The second is to create relations, and the ability to maintain those relations. So it is important for me to get some kind of contact information, so I can keep in touch. Perhaps via mail or an rss-feed. A third reason is if you do not connect with the people who show interest to what you write you will miss out on opportunities to make a sale. Be it a consultancy hour, a product or an exchange of knowledge.

So we want a way to keep track of all our users. We can get them to register an account and then log in every time they write a comment. But that is sometimes a to big step to take in order to just write a short comment. So we want to make it possible for users to enter a comment without first creating an account. But then we have he issue of blocking spamers. If you allow anyone to write comments then you will end up having a large amount of very squad comments on your posts. So in order to prevent that we could use some kind of chapcha, or we could be a bit creative and see how that goes. But in any case I would argue for usage of some kind of spam filter, that at least will block suspicious comments until you have approved them.
But even though we will allow users to create semi anonymous comments we might want to use some different techniques recognise them. And amongst storing the ip-address and browsers User Agent we could also record the typing speed of the user or the time between key letters. One could also use cookies and browser databases. But I will not cover that in this post, I will try some different approaches and then write a post about it later. So that you have something to look forward to ;)

So let's start out by creating the table for handling comments.

CREATE TABLE IF NOT EXISTS `comment` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `comment` text COLLATE utf8mb4_bin NOT NULL,
  `date` datetime NOT NULL,
  `user_id` int(11) NOT NULL,
  `name` varchar(50) COLLATE utf8mb4_bin NOT NULL,
  `mail` varchar(50) COLLATE utf8mb4_bin NOT NULL,
  `type` int(11) NOT NULL,
  `item` int(11) NOT NULL,
  `is_blocked` tinyint(4) NOT NULL,
  `is_deleted` tinyint(4) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=1 ;

Most of the columns are kind of clear. But there are some that might need explaining. For instance type is used to reuse the comment table on more than just posts, I might create other types of content on my site. Like page or course and then I give each of them an id. The item then represents the item of that type. So in case of post 1 I will use type = 1 and item = 1. And a comment on page 1 might get type = 0 and item = 1. Then we have is_blocked which I will use if I suspect that the post contain spam. Which mean I'll have to manually activate or delete it. And the last one is_deleted will be set to 1 if I or the logged in user manually delete the post. That means that a post is never really gone. It is just hidden. So if I have to go back to resolve a dispute, I actually have a complete track of the comments even though some of them might have been deleted. The name and mail columns are there for the commentator to allow you to display their name and to be able to contact them again.

Now we want to create a form for making a comment. And in order to create the first draft of code, enter the url index.php?module=comment&view=edit&generate=code. Now we have a file called views/comment/edit.php. I rename it to add.php, because this is what we want to use this form for. Then I rewrite the code as follows.

<?php
    $com = new Comment();
    if (Http::filter_input(INPUT_POST, 'send', FILTER_SANITIZE_URL) != '') {
        $com->id = Http::filter_input(INPUT_POST, 'id');
        $com->comment = Http::filter_input(INPUT_POST, 'comment');
        $com->date = date('Y-m-d H:i:s');
        $com->userId = Http::filter_input(INPUT_POST, 'user_id');
        $com->name = Http::filter_input(INPUT_POST, 'name');
        $com->mail = Http::filter_input(INPUT_POST, 'mail');
        $com->type = Http::filter_input(INPUT_POST, 'type');
        $com->item = Http::filter_input(INPUT_POST, 'item');
        $com->isBlocked = $com->isSpam();
        $com->isDeleted = 0;
        $com->tracker = Http::filter_input(INPUT_POST, 'tracker');
        $com->update();
        ?>
        <div class="information">
            Changes are saved
        </div>
        <?php
    }
?>
<div>
<h1>Comment</h1>
<form method="post" action="">
    <input type="hidden" name="user_id" value="<?php echo $user->id; ?>">
    <input type="hidden" value="<?php echo $type; ?>" name="type">
    <input type="hidden" value="<?php echo $obj->id; ?>" name="item">
    <table class="form">
            <tr>
                <th>
                    Comment
                </th>
                <td>
                    <textarea name="comment" style="width: 100%; height: 80px;"></textarea>
                </td>
            </tr>
            <tr>
                <th>
                    Name
                </th>
                <td>
                    <input 
                           type="text"
                           value=""
                           name="name" 
                        >
                </td>
            </tr>
            <tr>
                <th>
                  Mail <em>(Not public)</em>
                </th>
                <td>
                    <input 
                           type="text"
                           value=""
                           name="mail" 
                        >
                </td>
            </tr>
            <tr>
                <th></th>
                <td>
                    <input type="submit" name="send" value="Comment" class="button">
                </td>
            </tr>
    </table>
</form>
</div>

We also want to display a list of comments below our add form. So we generate the code for a list and rename it comments.php. Use index.php? module=comment&view=list&generate=code

<?php
    $com = new Comment();
    if (Http::filter_input(INPUT_GET, 'cmd') == 'del') {
        if (Http::filter_input(INPUT_GET, 'ok') == '') {
            ?>
            <div class="warning">
                <h2>Delete Comment</h2>
                Are you sure you want to delete this entry?<br><br>
                <a href="?module=<?php echo $module; ?>&view=list&id=<?php echo $id; ?>&cmd=del&ok=yes" class="button">Yes</a>
                <a href="?module=<?php echo $module; ?>&view=list" class="button">No</a>
            </div>
            <?php
            return false;
        } else if (Http::filter_input(INPUT_GET, 'ok') == 'yes') {
            $com->isDeleted = 1;
            $com->update();
            ?>
            <div class="warning">
                The Comment entry has been deleted.
            </div>
            <?php
        } 
    }

    $srchQry = ' is_deleted=0 AND is_blocked=0 AND type=' . $type . ' AND item=' . $obj->id . ' ';
    
    $orderBy = 'id';
    $desc = 'DESC';

    $order = 'orderby=' . $orderBy . '&desc=' . Http::filter_input(INPUT_GET, 'desc', FILTER_SANITIZE_URL);
    $orderBy = ' ORDER BY ' . $orderBy . ' ' . $desc;

    $postsPerPage = 20; // How many posts do you want to show per page
    $currentPage = (int)Http::filter_input(INPUT_GET, 'current_page', FILTER_SANITIZE_NUMBER_INT);
    if ($currentPage == 0) { $currentPage = 1; } // We are on page 1 as default when current_page is not set.
    $index = ($currentPage * $postsPerPage) - $postsPerPage;
    $limit = '';
    if ($page != 0) {
        $limit = " LIMIT $index, $postsPerPage";
    }
    $total = $com->fetchCount(' WHERE ' . $srchQry);
    $list = $com->fetchArray(' WHERE ' . $srchQry . ' ' . $orderBy . ' ' . $limit);
    $pages = ceil((($total-1)/$postsPerPage));
    
    $query  = '&search_text=' . $searchText
            ;

    $pData  = '&module=' . $module
            . '&view=' . $view
            . '&id=' . $id
            ;

    $params = $pData
            . $query 
            ;
?>
<div>
    <h1>Comments</h1>
    <?php echo $total; ?> post<?php if ($total > 1) { echo 's'; } ?> found<br>
    <?php foreach ($list as $item) { ?>
        <div class="comment">
            <p>
                <?php echo $item->comment; ?>
            </p>
            <p><i>
                <?php echo $item->date; ?> - 

                <?php
                if ($item->userId > 0) {
                    $sc = new User((int)$item->userId);
                    echo $sc->table_data[1];
                } else {
                    echo $item->name;
                }
                ?>
              </i></p>
            <!--
            We save the delete button for later
            <a href="?module=<?php echo $module; ?>&view=<?php echo $view; ?>&id=<?php echo $item->id; ?>&cmd=del">Delete</a>
            -->
        </div>
    <?php } ?>
    <div><?php echo Html::paging($page, $pages, '&module=' . $module . '&id=' . $com->id . '&view=' . $view . '&' . $query . '&' . $order); ?></div>
</div>

If you look closely at the add form I have created a function called isSpam(). This is empty for now, but in order to everything to work we need to create the Comment class.

<?php
class Comment extends Db {
    public $table = 'comment';
    
    function isSpam() {
        // For now we have no filter so we consider all comments to be free of spam.
        return false;
    }
}

Now we have all the code we need to include the comments in to the bottom of our post page. And do not forget to set the $type = 1; Here we add it to the div called comment_area.

<?php
$headerData->title = $obj->title;
$headerData->description = $obj->summary;
$headerData->keywords = $obj->tags;
?>
<div>
    <!--<img src="graphics/banner.png" style="margin-left:-20px; margin-top: -20px; width: 898px;">-->
    <h1><?php echo $obj->title; ?></h1>
    <p><?php echo $obj->message; ?></p>
    <p><i><?php echo $obj->posted; ?> - 
    <?php echo $obj->tags; ?></i></p>
</div>

<div id="comment_area">
    <?php $type = 1; ?>
    <?php include('views/comment/add.php'); ?>
    <?php include('views/comment/comments.php'); ?>
</div>

Now you can play around with styling. But for now I'm actually gonna let it be like this. I'll modify it when I start to see some comments. Because then I get some real data to look at, and I know that the comments are being used.

- Framework, PHP, Comments

<< Snap menu on top Send me an email >>

Comment

Name
Mail (Not public)
Send mail uppdates on new comments

Comments

0 post found