Creating a Book-like PHP Guestbook
Join the DZone community and get the full member experience.
Join For FreeLive Demo
download in package
Now – download the source files and lets start coding !
Step 1. SQL
We need to add one table to our database (to store our records):
CREATE TABLE IF NOT EXISTS `s178_guestbook` ( `id` int(10) unsigned NOT NULL auto_increment, `name` varchar(255) default '', `email` varchar(255) default '', `description` varchar(255) default '', `when` int(11) NOT NULL default '0', `ip` varchar(20) default NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
Step 2. PHP
Here are source code of our main file:
guestbook.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 // get visitor IP 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; } // get last guestbook records function getLastRecords($iLimit = 3) { $sRecords = ''; $aRecords = $GLOBALS['MySQL']->getAll("SELECT * FROM `s178_guestbook` ORDER BY `id` DESC LIMIT {$iLimit}"); foreach ($aRecords as $i => $aInfo) { $sWhen = date('F j, Y H:i', $aInfo['when']); $sRecords .= <<<EOF <div class="record" id="{$aInfo['id']}"> <p>Record from {$aInfo['name']} <span>({$sWhen})</span>:</p> <p>{$aInfo['description']}</p> </div> EOF; } return $sRecords; } if ($_POST) { // accepting new records $sIp = getVisitorIP(); $sName = $GLOBALS['MySQL']->escape(strip_tags($_POST['name'])); $sEmail = $GLOBALS['MySQL']->escape(strip_tags($_POST['name'])); $sDesc = $GLOBALS['MySQL']->escape(strip_tags($_POST['text'])); if ($sName && $sEmail && $sDesc && $sIp) { // spam protection $iOldId = $GLOBALS['MySQL']->getOne("SELECT `id` FROM `s178_guestbook` WHERE `ip` = '{$sIp}' AND `when` >= UNIX_TIMESTAMP() - 600 LIMIT 1"); if (! $iOldId) { // allow to add comment $GLOBALS['MySQL']->res("INSERT INTO `s178_guestbook` SET `name` = '{$sName}', `email` = '{$sEmail}', `description` = '{$sDesc}', `when` = UNIX_TIMESTAMP(), `ip` = '{$sIp}'"); // drawing last 10 records $sOut = getLastRecords(); echo $sOut; exit; } } echo 1; exit; } // drawing last 10 records $sRecords = getLastRecords(); ob_start(); ?> <div class="container" id="records"> <div id="col1"> <h2>Guestbook Records</h2> <div id="records_list"><?= $sRecords ?></div> </div> <div id="col2"> <h2>Add your record here</h2> <script type="text/javascript"> function submitComment(e) { var name = $('#name').val(); var email = $('#email').val(); var text = $('#text').val(); if (name && email && text) { $.post('guestbook.php', { 'name': name, 'email': email, 'text': text }, function(data){ if (data != '1') { $('#records_list').fadeOut(1000, function () { $(this).html(data); $(this).fadeIn(1000); }); } else { $('#warning2').fadeIn(2000, function () { $(this).fadeOut(2000); }); } } ); } else { $('#warning1').fadeIn(2000, function () { $(this).fadeOut(2000); }); } }; </script> <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>Your email: </label></td><td class="field"><input type="text" value="" title="Please enter your email" id="email" /></td></tr> <tr><td class="label"><label>Comment: </label></td><td class="field"><textarea name="text" id="text" maxlength="255"></textarea></td></tr> <tr><td class="label"> </td><td class="field"> <div id="warning1" style="display:none">Don`t forget to fill all required fields</div> <div id="warning2" style="display:none">You can post no more than one comment every 10 minutes (spam protection)</div> <input type="submit" value="Submit" /> </td></tr> </table> </form> </div> </div> <? $sGuestbookBlock = ob_get_clean(); ?> <!DOCTYPE html> <html lang="en" > <head> <meta charset="utf-8" /> <title>PHP guestbook | Script Tutorials</title> <link href="css/main.css" rel="stylesheet" type="text/css" /> <!--[if lt IE 9]> <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <script src="http://code.jquery.com/jquery-latest.min.js"></script> </head> <body> <?= $sGuestbookBlock ?> <footer> <h2>PHP guestbook</h2> <a href="http://www.script-tutorials.com/php-guestbook/" class="stuts">Back to original tutorial on <span>Script Tutorials</span></a> </footer> </body> </html>
When we open this page we will see a book, at the left side we will draw a list of the last three records, at the right – new records. When we submit the form a script will send POST data (to same php page), the script will save this data to the database, and it will return a list of 3 fresh records. Then, via the fading effect we draw returned data at left column. All of the code contains comments – read it for better understanding of the code. Ok, the next PHP file is:
classes/CMySQL.php
This is my own service class to work with the database. This is a nice class which you can use too. Database connection details are located in this class in a few variables so that you will able to configure this to your database. I don`t will publish its sources – this is not necessary for now. It's available in a package.
Step 3. CSS
Now – all used CSS styles:
css/main.css
*{ margin:0; padding:0; } body { background-color:#fff; color:#fff; font:14px/1.3 Arial,sans-serif; } 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 { background: transparent url(../images/book_open.jpg) no-repeat top center ; color: #000000; height: 600px; margin: 20px auto; overflow: hidden; padding: 35px 100px; position: relative; width: 600px; } #col1, #col2 { float: left; margin: 0 10px; overflow: hidden; text-align: center; width: 280px; } #col1 { -webkit-transform: rotate(3deg); -moz-transform: rotate(3deg); -ms-transform: rotate(3deg); -o-transform: rotate(3deg); } #records form { margin:10px 0; padding:10px; text-align:left; } #records table td.label { color: #000; font-size: 13px; padding-right: 3px; text-align: right; } #records table label { font-size: 12px; vertical-align: middle; } #records table td.field input, #records table td.field textarea { background-color: rgba(255, 255, 255, 0.4); border: 0px solid #96A6C5; font-family: Verdana,Arial,sans-serif; font-size: 13px; margin-top: 2px; padding: 6px; width: 190px; } #records table td.field input[type=submit] { background-color: rgba(200, 200, 200, 0.4); cursor: pointer; float:right; width: 100px; } #records table td.field input[type=submit]:hover { background-color: rgba(200, 200, 200, 0.8); } #records_list { text-align:left; } #records_list .record { border-top: 1px solid #000000; font-size: 13px; padding: 10px; } #records_list .record:first-child { border-top-width:0px; } #records_list .record p:first-child { font-weight:bold; font-size:11px; }
Live Demo
download in archive
Conclusion
Today we have prepared great PHP guestbook for your website. Sure that this material will be useful for your own projects. Good luck in your work!
Opinions expressed by DZone contributors are their own.
Comments