Shoutbox with PHP

Create a Basic Shoutbox with PHP and SQL

In this tutorial, we will be creating a basic ‘Shoutbox’ system with PHP. Aimed at beginners to PHP development, this allows you to get your feet wet working with databases before moving on to some of the more advanced PHP tutorials here at NETTUTS.

Introduction

This tutorial will guide you through the process of creating a basic “shoutbox” with PHP, using a MySQL database to store the shouts – and then make it look nice with some CSS. The tutorial is aimed at designers who are confident with HTML & CSS, but want to try their hand at developing with PHP.

Following the tutorial, you should hopefully have a good understanding of the basics of using PHP to communicate with a database to send, request and receive information. We will also be including the use of Gravatars in our Shoutbox, adding that little extra oomph!

For those who haven’t, I recommend you read our PHP From Scratch series in order to understand exactly what PHP is, and get a look at some of the basic syntax and how we use variables.

The sources files are also commented for those who would prefer to learn that way.

Step 1 – Getting Started

Database

Before starting, you should already have a database setup on your web server. Make sure you have the following details at hand:

  • Hostname (eg. localhost)
  • Database name
  • Username for database
  • Password

In the database, you will need to create a table named shouts with five fields:

  • id
  • name
  • email
  • post
  • ipaddress

To create this, run the following SQL code. You will normally run this from the SQL tab in phpMyAdmin.

CREATE TABLE `shouts` (
  `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(45) NOT NULL,
  `email` VARCHAR(60) NOT NULL,
  `post` TEXT NOT NULL,
  `ipaddress` VARCHAR(45) NOT NULL,
  PRIMARY KEY (`id`)
);

You should receive a “Your SQL query has been executed successfully” message

The Files

We will need three files created for this project:

  • index.php
  • style.css
  • db.php

You will also need a folder with our required images. Grab this from the source files.

Database Connection Details

The db.php file will be used to store our database details. Open it and insert the following code:

<?php
$host = 'localhost'; //usually localhost
$username = 'root'; //your username assigned to your database
$password = 'password'; //your password assigned to your user & database
$database = 'shoutbox'; //your database name
?>

Step 2 – Interaction

Start your index.php file with the following code, it just begins our document and places a few sections to style later.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Shoutbox for NETTUTS by Dan Harper
<link rel="stylesheet" href="style.css" type="text/css" />
</head>
<body>
<div id="container">

  <h1>Shoutbox
  <h5><a href="http://www.danharper.me" title="Dan Harper">Dan Harper </a> : <a href="http://www.nettuts.com" title="NETTUTS - Spoonfed Coding Skills">NETTUTS</a></h5>

  <div id="boxtop" />
  <div id="content">

Establishing a Connection

Before we can do anything with a database, we need to connect to it. Insert the following after the previous code. It is explained below.

<?php
$self = $_SERVER['PHP_SELF']; //the $self variable equals this file
$ipaddress = ("$_SERVER[REMOTE_ADDR]"); //the $ipaddress var equals users IP
include ('db.php'); // for db details

$connect = mysql_connect($host,$username,$password) or die('

Unable to connect to the database server at this time.

'); mysql_select_db($database,$connect) or die('

Unable to connect to the database at this time.

');

The first two lines use a built-in PHP function to get the name of this file, and the other line to get the visitors IP address. We will use the two variables later in the tutorial.

We then include our db.php file so we can retrieve the database details you filled in. Alternatively, you could paste everything from db.php here, but it’s good practice to separate the details.

$connect stores a function to use our database details in order to establish a connection with the database server. If it can’t connect, it will display an error message and stop the rest of the page loading with die().

Finally, we connect to our database.

Has anything been submitted?

The next thing we will do is check whether someone has submitted a shout using the form (which we will include shortly). We check the documents POST to see if something has been submitted from a form.

if(isset($_POST['send'])) {
    if(empty($_POST['name']) || empty($_POST['email']) || empty($_POST['post'])) {
        echo('

You did not fill in a required field.

'); } else {

We start with our if() which checks our POST to see if an item named ‘send’ has been submitted. If it has we use the empty() function to make sure the ‘name’, ‘email’ and ‘post’ fields were filled in. If they weren’t, we display an error.

Otherwise, we continue:

$name = htmlspecialchars(mysql_real_escape_string($_POST['name'])); 
$email = htmlspecialchars(mysql_real_escape_string($_POST['email'])); 
$post = htmlspecialchars(mysql_real_escape_string($_POST['post']));

$sql = "INSERT INTO shouts SET name='$name', email='$email', post='$post', ipaddress='$ipaddress';";

    if (@mysql_query($sql)) {
        echo('

Thanks for shouting!

'); } else { echo('

There was an unexpected error when submitting your shout.

'); } } }

On the first three lines, we run each of our fields (name, email and post) through the htmlspecialchars() and mysql_real_escape_string() functions and place them into their own variables.

htmlspecialchars() is a function designed to prevent users from submitting HTML code. If we didn’t do this, someone could put any HTML into our database which would then be executed to other users. This is especially bad if someone submitted javascript code that would transfer visitors to a malicious website!

mysql_real_escape_string() is a similar function. Except this one stops the user from submitting any sort of SQL code to the server. If we didn’t do this, someone could execute code to steal, edit or erase our database!

Using our new details, we create a SQL query to insert the submitted shout into the database. In the if() tags, we execute the SQL Query. If the query was successfully executed, and the shout added to the database, we display a “Thanks for shouting!” message; otherwise we display an error.

Retrieving the Shouts

We will now retrieve the 8 latest shouts from our database to display them to the user.

$query = "SELECT * FROM `shouts` ORDER BY `id` DESC LIMIT 8;";
    
$result = @mysql_query("$query") or die('

There was an unexpected error grabbing shouts from the database.

'); ?>

    On the first line, we create a new SQL query to "Retrieve all fields from the 'shouts' table, order them descending by the 'ID'; but only give us the latest 8".

    On the second line we execute the query and store it in $result. We now:

    while ($row = mysql_fetch_array($result)) {
    
        $ename = stripslashes($row['name']);
        $eemail = stripslashes($row['email']);
        $epost = stripslashes($row['post']);
        
        $grav_url = "http://www.gravatar.com/avatar.php?gravatar_id=".md5(strtolower($eemail))."&size=70"; 
        
        echo('
  • Gravatar

    '.$ename.'

    '.$epost.'

  • '); } ?>

The first line says "While there are still rows (results) inside $result, display them as follows:".

stripslashes() removes any slashes which mysql_real_escape_string() may have inserted into submissions.

$grav_url creates our Gravatar from each users email address.

We then output (echo) each shout in a specific manner. Basically displaying the Gravatar, Name and Shout in a list we can easily style later.

The Form

The final step for this page is to include a form to the bottom of the page which users can submit posts through.

<form action="<?php $self ?>" method="post">
<h2>Shout! </h2>
<div class="fname">

Note that we reference the $self variable to tell the form where to send it's results; and we also send via the POST method. Below the form we close off any HTML tags we opened.

Styling

Try it out! You've finished all the PHP code, and you should be able to add a new shout and see the 8 latest ones.

However, there's one problem. It looks UGLY! Lets sort that out with some CSS :) With this not being a CSS tutorial, I won't go over any of the styling, but everything's pretty basic.

* {
margin: 0;
padding: 0;
}

body {
background: #323f66 top center url("images/back.png") no-repeat;
color: #ffffff;
font-family: Helvetica, Arial, Verdana, sans-serif;
}

h1 {
font-size: 3.5em;
letter-spacing: -1px;
background: url("images/shoutbox.png") no-repeat;
width: 303px;
margin: 0 auto;
text-indent: -9999em;
color: #33ccff;
}

h2 {
font-size: 2em;
letter-spacing: -1px;
background: url("images/shout.png") no-repeat;
width: 119px;
text-indent: -9999em;
color: #33ccff;
clear: both;
margin: 15px 0;
}

h5 a:link, h5 a:visited {
color: #ffffff;
text-decoration: none;
}

h5 a:hover, h5 a:active, h5 a:focus {
border-bottom: 1px solid #fff;
}

p {
font-size: 0.9em;
line-height: 1.3em;
font-family: Lucida Sans Unicode, Helvetica, Arial, Verdana, sans-serif;
}

p.error {
background-color: #603131;
border: 1px solid #5c2d2d;
width: 260px;
padding: 10px;
margin-bottom: 15px;
}

p.success {
background-color: #313d60;
border: 1px solid #2d395c;
width: 260px;
padding: 10px;
margin-bottom: 15px;
}

#container {
width: 664px;
margin: 20px auto;
text-align: center;
}

	#boxtop {
	margin: 30px auto 0px;
	background: url("images/top.png") no-repeat;
	width: 663px;
	height: 23px;
	}

	
	#boxbot {
	margin: 0px auto 30px;
	background: url("images/bot.png") no-repeat;
	width: 664px;
	height: 25px;
	}

	#content {
	margin: 0 auto;
	width: 664px;
	text-align: left;
	background: url("images/bg.png") repeat-y;
	padding: 15px 35px;
	}
	
    #content ul {
    margin-left: 0;
    margin-bottom: 15px;
    }
    
    #content ul li {
    list-style: none;
    clear: both;
    padding-top: 30px;
    }
    
        #content ul li:first-child {
        padding-top:0;
        }
    
    .meta {
    width: 85px;
    text-align: left;
    float: left;
    min-height: 110px;
    font-weight: bold;
    }
    
        .meta img {
        padding: 5px;
        background-color: #313d60;
        }
        
        .meta p {
        font-size: 0.8em;
        }
    
    .shout {
    width: 500px;
    float: left;
    margin-left: 15px;
    min-height: 110px;
    padding-top: 5px;
    }
    
    form {
    clear: both;
    margin-top: 135px !important;
    }
    
        .fname, .femail {
        width: 222px;
        float: left;
        }
        
        form p {
        font-weight: bold;
        margin-bottom: 3px;
        }
        
        form textarea {
        width: 365px;
        overflow: hidden; /* removes vertical scrollbar in IE */
        }
    
        form input, form textarea {
        background-color: #313d60;
        border: 1px solid #2d395c;
        color: #ffffff;
        padding: 5px;
        font-family: Lucida Sans Unicode, Helvetica, Arial, Verdana, sans-serif;
        margin-bottom: 10px;
        }

Conclusion

So there you have it! A great-looking, fully functional Shoutbox! You may have wondered what the point of creating a Shoutbox is, and well, you're right, there is no point. But what this does do is help give you some vital basic understanding of using PHP to work with a database, allowing you to move on to much more advanced guides here at NETTUTS.

Heck, you could even reuse this code to create yourself an incredibly basic blog! Not much point to it, but it's fun.

Dan Harper is danharper on Themeforest
Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • http://joshmmiller.com Josh

    Thanks for the great tut! I love that Nettuts is helping those that don’t have too much PHP experience :D

  • http://www.kenseikai-jujitsu-sussex.co.uk Ben Swift

    Wow, thanks! Nice tutorial!

  • Eissoj

    Nice tutorial Dan,

    I dislike making a shoutbox or guestbox, but now I got a nice example :D Thanks

  • http://xseria.com Sam Parkinson

    A nice script for beginners. Some useful info regarding database connections as well, thanks.

  • http://www.kevinquillen.com/ Kevin Quillen

    Nice, though I would advise using a MySQL GUI client like HeidiSQL instead of phpMyAdmin.

  • http://micromedia.cz Ginnex

    Well, very nice tut for beginers but there is one little mistake or misunderstand. The reason why you call the stripslashes is propably not what you think. The right reason might be magic_quotes_gpc set on which means that you escape the string twice. The first time it’s done by magic_quotes_gpc automatically and then you do it manually using mysql_real_escape_string (http://cz2.php.net/manual/en/function.get-magic-quotes-gpc.php look at examples). If you want to print anything from database which was written by users I also recommend using htmlspecialchars() (http://cz2.php.net/manual/en/function.htmlspecialchars.php)

    This function escapes chars like “” which can ruin your html code and be easilly used for XSS attack.

  • http://www.ben-griffiths.com Ben Griffiths

    Does exactly what it says on the tin, and great for beginners :)

  • http://www.themolitor.com Chris Molitor

    This is great. I love basic database interaction tutorials.

  • http://www.innovationsopen.com mzee@richo

    Nice stuff :Next should be django or cakephp tutorial

  • Pingback: vot.eti.me

  • http://laminbarrow.com Lamin Barrow

    Very nice tut. I took Shane’s advice and now i learning this PHP stuff. Thanks very much.

  • http://www.freshclickmedia.com Shane

    Nice example – real-world stuff like this is very good to see.

    Thanks.

  • http://www.instantshift.com Roshan

    Thanks for tips. It provides a basic platform for further development.
    Not saying its the best but basic.

    Roshan
    Freelance Developer
    http://www.instantshift.com

  • http://freewarecollection.co.cc Freeware Collection

    Thanks for your tut. I think it’s useful for beginers of PHP. I love the way you write tuts here because I learn to much from this. Thanks.

  • Mr. Magic

    I’m probably going to sound like a real nitpick, but I think it would be good to teach beginning PHP programmers some good practices, so I’m going to point out some mistakes in your otherwise good article:

    First, while not exactly a mistake, you’re making the email field only 60 characters long. While it may seem like a long-enough field, it’s possible to have a much longer email address – I have one, but I don’t use it very often. Still, it would be good to think ahead and make the field longer.

    Next, you have these two lines:
    $ipaddress = (“$_SERVER[REMOTE_ADDR]“); //the $ipaddress var equals users IP
    include (‘db.php’); // for db details

    Why is the $_SERVER['REMOTE_ADDR'] placed inside not only quotes, but braces? Just $ipaddress = $_SERVER['REMOTE_ADDR']; would suffice.
    include is a language construct, thus it does not require braces, and they should be omitted:
    include ‘db.php’;

    Your HTML markup is also mixing lower and upper case tags. Pick a case and stick to it – consistency is a good thing.

    It is unnecessary to add a ; in the end of the SQL query when executing it in PHP.

    Then, you’re again putting variables inside quotes for no apparent reason:
    $result = @mysql_query(“$query”) or die

    Just do @mysql_query($query) – the quotes are absolutely unnecessary.

    You’re using braces with echo, which is a language construct like include. As such, the braces are unnecessary and should be omitted.

    It also seems like you’re using short tags instead of , which is not recommended as the short tags will likely be removed in future PHP versions – however I’m not sure about this one, as the formatting seems to be a bit screwed.

  • http://www.lexperts.nl Lexperts

    You better can check your magic qoutes like this

    if(get_magic_quotes_gpc() == false)
    {

    $_POST = array_map(“addslashes”, $_POST);
    $_GET = array_map(“addslashes”, $_GET);
    $_COOKIE = array_map(“addslashes”, $_COOKIE);

    }

    Input:

    htmlspecialchars do NOT use it when you insert something. Only use mysql_real_escape_string and trim to strip whitespace from the beginning and end of a string.

    Output:

    For the output use this functie’s

    filter_output without enters ():

    function filter_output($string)
    {

    return htmlspecialchars(stripslashes($string));

    }

    filter_output with enters ():

    function filter_output_all($string)
    {

    return nl2br(htmlspecialchars(stripslashes($string)));

    }

    The global $_SERVER is also not safe. Use this to make it safe: #
    echo htmlentities(strip_tags($_SERVER['PHP_SELF']));

  • Mr. Magic

    Ok please tell me how $_SERVER['PHP_SELF'] is unsafe?

  • http://www.pcblog.cz Chates

    They say its better to use mysqli_ functions instead of mysql_. It should be better. But there are little differences in implementation.

  • http://www.danharper.me Dan Harper

    Thanks for all your feedback!

    Using () and “” is really just a habit of mine which I picked up from SitePoint books. I should really stop doing that.

    And thanks for your comments about using magic quotes. I completely forgot about that! I’m used to developing on a server where it’s disabled. I should really do that anyway, though.

    But I can’t see where I used upper-case HTML? I never do that…

    Thanks again!

  • Mr. Magic

    (‘Unable to connect to the database at this time.’);

  • http://www.lexperts.nl Lexperts

    You can make a cross-site script. For example. Your form is “test.php”. And you try this:
    http://localhost/test.php/“><script>alert(‘check’)</script>

    Here is your bug :)

  • http://www.designbykai.nl Kai

    Thank you very much for this beautifull tutorial!! :)

  • http://vailo.wordpress.com Niklas

    Simple and useful tutorial. Thanks.

  • daniel

    cool tutorial though! thanks for sharing ;)

  • Fynn

    @ Dan Harper

    LOL didn’t you see? You used uppercase at the title-tag, the h1-tag, the p-tag and the label-tag :P

    But it’s a nice article, gonna give it a shot tomorrow!

    thanks

  • http://www.danharper.me Dan Harper

    Thats wierd. When I’m in IE, I see them in uppercase, but in FF they’re in lower-case but don’t have a closing tag :S

    It’s probably a glitch from WordPress or something, since the source code (in the download) is fine.

  • http://www.image2markup.com Ivan

    Oh c’mon people, a shoutbox?? Kids with ZERO PHP knowledge do things like that. Give us tutorials for the real devs, not kid stuff!

  • http://www.danharper.me Dan Harper

    @Ivan That’s the point. This is aimed at beginners so they can understand some of the basics before moving to the more advanced tutorials here.

  • http://james.padolsey.com James

    Nicely written tut Dan! :)

    There must be a problem with the syntax highlighter or WordPress because on all posts in NETTUTS where the empty() method is included in the code, it ends up spitting out two so it becomes emptyempty() – To see what I mean look at the code block under the heading, “Has anything been submitted?”…

  • http://inspirationup.com Joefrey Mahusay

    Very simple.

  • headlesslizard

    I enjoy php, however one thing I don’t have in the blog code etc. that I design is “mysql_real_escape_string()”, is this really needed if I stop people from executing html?

  • http://www.kevinquillen.com/ Kevin Quillen

    Well for introductory purposes, it gets the uninitiated using PHP and MySQL. Best practices and security can be learned later. Its a good tut to ease someone into the language and interacting with a database.

  • http://www.insicdesigns.info insic

    hmm coolness. i did more or less like this before except the gravatar integration.

  • http://harrymahardhika.com Harry M

    Nice tuts…

  • http://www.brainwashfactory.org i.

    nice tutorial, but i’m not keen on using “TEXT” fields in the database.

    Using TEXT or BLOB gives users the possibility to paste giants amounts of text just to flood your database or make your site look ugly.

    Another point is flooding/spamming the shoutbox with large amounts of shouts. As we’re already storing the ipadress in the database, it wouldn’t be tough to check before each insert if that certain ipadress did post anything the last x minutes or seconds and if yes reject it or sth.

    just my 2 cents.

    best regards

  • davros

    I’m not sure what’s worse, the article or the sycophantic comments

  • http://www.setsailmedia.com/ Patrick Moore

    Nice tutorial! Is there a reason that you didn’t close the MySQL connection thread? Leaving it open, if the site grows to a substantial size, is going to create lots of congestion problems. Best to use

    mysql_close();

    at the end of the insertion script.

  • http://www.emrahdodanli.com iddaa
  • http://taylorsatula.co.cc/ Taylor Satula

    When I saw this im my feed I almost didn’t come ( I doubted you NETTUTS, I have sinned). But this made it so nice also it is a good PHP trainer for me. I’m not too good at PHP so this is a big help to me

  • Eduardo

    Please fix the code. there is a huge block of code that is supposed to be on the explanation part.
    thank you for this tutorial.

  • Casey

    I noticed in the beginning of step 2, the first code section has a error in the coding. If you look on line 11 you will see the tag never gets closed. :) Bonus Points for me!

  • Casey

    I apologize for double posting, but I also noticed in step 2, same code section. Line 5 is missing its closing tag. If I find any more errors, I will post again :)

  • http://qtiw Jhonny

    Parece que esta bien

  • http://www.marketfishing.com marketfishing

    Large selection of name brand discount and wholesale fishing tackle, gear, rods and reels.http://www.marketfishing.com

  • http://ass.com Bob

    looks more like a guestbook to me

  • http://csstemplatesfree.net cssdesigner

    Good work! It is very useful for beginners.
    But please fix problem with highlighter.

  • http://www.websparkdesign.com Blakeley

    Thanks so much for the tutorial! It was really helpful for someone who’s just getting into PHP/MySQL – real world examples are always nice. Thanks for taking the time to make this.

  • http://www.spmmf.com mmf

    not bad

  • http://hellowiki.com fen

    Thank you, good for a newbie.

  • arshad

    wonderful … i just found your site via digg and am really happy about it .thx guys :)