PHP Tutorial- Part 2
Project Guestbook

<< Page 1 Page 2 Page 3 Page 4 >>

 



Richard H. Nilsson, July 10, 2003
(Updated for PHP 5, Feburary, 2006)

Create a message entry form

In Part 1, we created a database and built a table in it called "Messages". The table has fields into which we will store visitors contributed information. We could enter some information manually, but that would be tedious, using MySQL commands directly. Let's create a page with an HTML form that is enabled by PHP code, a real Web-application.

We will build the page using a top-down approach, starting with the CSS to format it, some form data verification scripting, the form processing handler, and finally the form itself:

Formating with CSS- The opening of our form page is pretty straightforward, just the header stuff, title and some CSS to define our look. You can adjust background and text colors easily. The "maincontent" specification sets up about 10% margins on either side of a centered form:

<html>
<head>
<title>Guest Entry</title>
<style type="text/css"><!--
body,p,td,li {
	font-family: arial,helvetica,sans-serif;
	font-size:12px; 
	color:#000;
	background:#eee;
	}
h1 {
	font:24px/1.2 arial,helvetica,sans-serif;
	font-weight:700;
	color:#fc0;
	}
#maincontent {
	width:80%;
	margin-left:auto;
	margin-right:auto;
	}
.auth {
	font:10px/1.2 arial, helvetica,sans-serif;
	color:#000;
	}
.sctn1hd {
	font:18px/1.0 arial,helvetica,sans-serif;
	font-weight:700;
	padding:4px;
	background:#ccc;
	color:#333;
	}
-->
</style>

Form Verification - When the form is submitted, we will want to check a few entries, like that the email is a valid U.S. or Euro-style construct, the visitor has supplied a name, and so on. We even require the email address entered twice for confirmation. We do not verify the Web link URL or other optional information. What's neat about this script is that it shows you all your errors at once in the alert:

<script type="text/javascript" language="JavaScript"><!--
function verify(form)
{
   var msg = "";
   var err = 0;
   var j = new RegExp();
   if (form["fname"].value == '')
   {
     msg += "You forgot to enter your first name.\n";
     err++;
   }
   if (form["lname"].value == '')
   {
     msg += "You forgot to enter your last name.\n";
     err++;
   }
   if (form["email"].value != form["email2"].value)
   {
     msg += "You must enter your email twice for confirmation.\n";
     err++;
   }
   // allow Euro-style and subdomain addresses 
   j.compile(/^[A-Za-z0-9._-]+@[A-Za-z0-9._-]+\.[A-Za-z0-9]{2,3}$/);
     if (!j.test(form["email"].value))
     {
       msg += "You must supply a valid email address.\n";
       err++;
     }
   if (form["comments"].value.length < 8)
   {
     msg += "You forgot to enter any comments.\n";
     err++;
   }
   if (err > 0)
   {
     msg = "_______________________________\n" + msg;
     msg = "Please correct the following form errors:\n\n" + msg;
     alert(msg);
     return false;
   }
   return true;
}
//-->
</script>
</head>

If all the checks result "true", the form is submitted according to the "action=" attribute in the form tag (more on that later).

Log In - Before we can enter any information into our Message table fields, we have to log in to the database. This requires telling MySQL which database we want and what our username and password are:

<body>
<div id="maincontent">
<p class="sctn1hd">Message Entry</p>
<?php
  $hostName = "localhost";
  $databaseName = "guestbook";
  $userName = "user";
  $passWord = "password";
  
  function showError()
  {
    echo("Error " . mysql_errno() . " : " . mysql_error());
  }
// log in
if (!($db = @ mysql_connect($hostName, $userName, $passWord)))
    showError();
// select our database
if (!( @ mysql_select_db($databaseName, $db)))
    showError();

We didn't close the <?php tag, because there is more code coming. The "showError()" function only executes if something goes wrong while loggin in, and displays an error in your page.

When the visitor hits the "Submit" button, we will have the form action re-load this page; this next code will detect that we've submitted, and send the form data to MySQL.

Passing Variables - To pass a form variable to a PHP page, you name the form element that contains the data you want to pass. For example, in this case our form has a button named "submit". When the form action attribute reloads the page, the variable "$submit" contains the button's value; in this case, "Submit", which is the title of the button. Other variables contain the visitors supplied information. "$comments", for instance, contains what she entered in the form input textarea named "comments".

After inserting the new visitor record into the database, we tell the visitor his entry worked, and build a mail message to send to ourself, notifying us whenever a visitor leaves an entry, and finally, we provide a "Return" button that sends the visitor back to the guestbook page:

list($userName, $mailDomain) = split("@", $_POST['email']);
if ($_POST['submit'] != "" and checkdnsrr($mailDomain, "MX"))
{
  // process form
  extract($_POST); // get submitted form data
  $comments = ereg_replace("<.+>", "", $comments); // strip HTML
  $sql = "INSERT INTO Messages (Time, Date, Fname, Lname, Email, URL, City, 
State, Country, Comments) VALUES (CURTIME(), CURDATE(), '$fname', '$lname',
'$email', '$url', '$city', '$state', '$country','$comments')"; $result = mysql_query($sql); echo "<p>Thank you.<br />Your entry was accepted.</p>\n"; // tell You there's a new entry $body = $comments; $body .= "\n--" . $fname . " " . $lname; $to = "Your Name <you@yourisp.com>"; $subject = "New entry in your guestbook"; // send ourself the message mail($to, $subject, $body); // provide 'return' button echo "<br /><br />\n<center><form action='javascript:history.go(-2)'>
<input type='submit' class='nav2' value='Return'></form>
</center><br />\n"; } else {

Capturing Form Data - As of PHP 5, to improve security, PHP's gobal data arrays are not automatically available to any script. The programmer must explicitly select the appropriate global data array he desires. When forms are submitted using the "POST" method, all the form imputs are contained in the $_POST array, keyed to the "name" attributes of the form elements. In other words, our vistor's email address will end up in the array element "$_POST['email']" because "email" is the name of the form input we collected it in. Similarly, if we had used the "GET" method of form submission, all the form inputs would be in the global $_GET array.

To prevent a type of form "spamming" or "email spoofing", we use a simple method of verifying the domain of the submitter's email address. We do this by first splitting the address up into the "userName" part and the "mailDomain" part, which are always separated by the "@" symbol. The name part is a "throwaway"; we're only concerned with knowing if the domain she entered is real. Spammers usually have a sneaky way of using temporary domains that are unregistered quickly after the thousands or millions of their spam messages are sent, to prevent tracing them and prevent return mail from flooding their mailboxes. The domain test is combined with the form submision test described next.

We also, in the same "if" statement, test to see if the script was called by the form being submitted by testing for the existence of the "submit" element of this array (the name of our "Submit" button element). If the script were simple accessed from another page by a link, $_POST['submit'] would not be "set". Executing the function "extract($_POST)" pulls each form data array element into a simple variable of the name of the form input element. For example, in our form the visitor's email address was saved in the form input element named "email". After the "extract($_POST)", the visitor's email address will have been copied from the global $_POST['email'] element to the simple variable string "$email.

Cleaning Up Entries - In the code block above, we we use PHP's "ereg_replace()" function to replace all code between and including the < and > symbols; in other words, we clean out any HTML tags that might be in the "$comments" form data variable.

Storing Entries - In the next line, we build an SQL query string, using the MySQL "INSERT" command. Note there is a one-to-one relationship between the Message table field names and variables captured from the form. Note also how the Time field gets set to CURTIME(), and the Date field to CURDATE(). These functions automatically pick up the server's time and date at the time the query is sent to MySQL.

Notice the "} else {"? That phrase breaks up the presentation of the page into two parts. If, like the first time it appears, the form was NOT submitted (no $submit variable yet exists) then we don't do the processing just described, we just show the form for visitor input:

// display the form
?>
<p>Fill in the blanks below to make an entry in my guestbook.<br />
"Name", "Email", and "Comments" entries are required. Don't put email 
addresses in your message - they will be visible to hostile web-bots.
Thanks!</p> <hr> <form name="form_one" method="post" action="<?php echo $_SERVER['PHP_SELF'];?>"
onSubmit="return verify(this);">

Notice the "action" attribute; we use a chunk of PHP to reload this page ("$_SERVER['PHP_SELF']" is the global variable containing the url of this page). Use of the "onSubmit" attribute causes the "action" to take effect after the JavaScript "verify()" function returns a "true" status (all the form entries passed our checks).

<table border="0">
  <tr>
    <td align="right">
      <strong>First Name:</strong></td>
    <td><input type="text" name="fname" size="20" maxlength="20" /></td>
  </tr>

Above is our first form entry, which because of its "name='fname'" attribute, will be available to PHP as "$_POST['fname']" when the form is submitted, and the page reloads. To continue:

  <tr>
    <td align="right">
      <strong>Last Name:</strong></td>
    <td><input type="text" name="lname" size="20" maxlength="20" /></td>
  </tr>
  <tr>
    <td align="right"><strong>E-Mail:</strong></td>
    <td> <input type="text" name="email" size="40" maxlength="40" /> 
e.g.:"you@yourhost.isp"</td> </tr> <tr> <td align="right"><strong>E-Mail:</strong></td> <td> <input type="text" name="email2" size="40" maxlength="40" />
again, for confirmation</td> </tr> <tr> <td align="right">URL:</td> <td> <input type="text" name="url" size="40" maxlength="80" />
e.g.:"http://yourhost.isp/yourpage"</td> </tr> <tr> <td align="right"> City:</td> <td> <input type="text" name="city" size="15" /> , State: <input type="text" name="state" size="5" maxlength="30" />
Country: <input type="text" value="USA" name="country"
size="15" maxlength="20" /></td> </tr> <tr> <td align="right"><strong>Comments:</strong></td> <td><textarea name="comments" cols="50" rows="4" maxlength="512"></textarea> </td> </tr> <tr> <td></td> <td><input name="submit" type="submit" value="Submit" />
<input name="reset" type="reset" /></td> </tr> </table> </form> <hr> * <a href="guestbook.php">Back to the Guestbook</a><br> <?php } // end display form ?> </div> </body> </html>

Note the double email entry for confirmation. It doesn't absolutely guarantee a correct address, but hopefully conveys the importance of checking it. The textarea input "name='comments'" is set to allow 512 characters. I estimate that at being about 8 to 10 lines of text. If you wish to allow more, increase the value in the "maxlength" attribute of that entry. The last bit of PHP closes the "else" clause of the "if" statement, by providing a right-brace. It is followed by the HTML that finishes the page.
Next - display the guestbook: go to Page 3 >>.


Copyright 2003 Richard Nilsson. Verbatim copying and redistribution of this entire article are permitted without royalty in any medium provided this notice is preserved.