WWW FAQs: How can I receive form submissions?


2006-07-28: There are two basic ways. The first, and by far the best, is to use a "server-side" extension language like PHP, ASP or a Perl CGI to handle your form submissions. Sprinkling just a little PHP or ASP code into a web page can enable it to do great things. If your web hosting account allows you to use one of these options, you should.

The second and greatly inferior choice is to use a mailto: URL as the action of your form. While this does get the form data to you, it does it in the worst possible, least convenient way, antagonizing the user in the process. I'll explain it for the sake of completeness, but you should use PHP or any of the other server-side solutions.

Accepting Form Submissions With PHP

There are literally dozens of "server-side extension" languages. Believe me, you don't want me to cover them all here. But PHP is both the most popular and the easiest to learn, and it is also used by large sites on a daily basis. What's more, you can run PHP at home for testing purposes, even on Windows.

So I'll demonstrate how to process a form submission in PHP. In this example, I'll append the submitted form data to a file and implement a simple guestbook. But you could also use PHP's database functions as described in Free Webmaster Help's PHP/MySQL tutorial.

Another option: transmit the submitted form data to yourself with PHP's highly convenient mail() function. This is still a big improvement over mailto:, because you can control the way the information is formatted.

PHP Basics

PHP is designed to let you insert code into an otherwise normal web page so that the page is enhanced with the ability to do things "on the fly," like handling form submissions and talking to databases. PHP pages are much like HTML pages, except that they must have a .php extension, they must reside on an actual web server (a web server running on your own computer for testing is just fine), and the web server in question must support PHP. Virtually all Linux web hosts support PHP, and most Windows hosts do too.
Important note: PHP is a big subject... but it's very easy to get started. Don't be afraid to experiment. And if you need more help, definitely check out the official PHP tutorial on www.php.net. For space reasons, it isn't possible to explain every feature of PHP I touch upon in this article. But you can bet it's all covered in glorious detail on www.php.net, the official home of PHP.

The following simple HTML page has been enhanced with PHP code that inserts the current date. This simple example is meant to show how PHP code is inserted into a page. Notice that the PHP code begins with <?php and ends with ?>. Everything between these two markers is code to be run by the PHP interpreter on the web server. The web browser never sees this code. If you see it when you click "view source," then:

1. You have not put your page on a web server yet and you're trying to load it from your own hard drive directly, which won't work, or

2. Your server doesn't support PHP, possibly because you haven't installed PHP yet, or

3. You forgot to give the page a .php extension instead of a .html extension (example: guestbook.php).

Copy and paste this code to a file called date.php on your web server and check it out in your web browser. If your web server supports PHP, you'll see the current date as part of the page:


<html>
<head>
<title>Today's Date</title>
</head>
<html>
<body>
<h1>Today's Date</h1>
<h2><?php echo(date('F j, Y'))?></h2>
</body>
</html>

What's happening here? PHP's echo statement sends its output to the user as part of the web page. And PHP's date function formats the current time any way you like. In this case I've chosen a format that puts the full name of the month first (F), then the day of the month (j), and then the four-digit year (Y).

Handling Forms In PHP

Now that you've seen the bare bones of PHP, we'll go after bigger game: a form submission. The next example is part of the code for my simple PHP guestbook. For simplicity's sake, I'll just show the code that displays the guestbook form and the code that adds a new guestbook entry to a file. You can find the complete code, including code to display the current guestbook entries and delete unwanted entries, in the article how do I add a guestbook to my website?

In PHP, form submissions appear as part of an "associative array" called $_POST— at least, if you set method="POST" for your form element, which I recommend. The POST method can handle any amount of form data. The GET method packs the data into the URL, so it is only appropriate for searches and other form submissions someone might actually want to bookmark and return to later. The rest of the time, it's just a way to make a big, ugly, buggy, insecure super-long URL.

But what is an associative array? An associative array is like a filing system. If you know what name something is filed under, you can locate it in the filing system. In PHP, $phoneNumbers['bob'] gives us back the phone number we filed under bob. And the special associative array $_POST is already conveniently filled up with all the data in the form the user submitted.

For more information about associative arrays in PHP, see the associative array tutorial on www.samspublishing.com.
What this means for us is simple. If the form element contains an input element called firstname, then we can fetch what the user typed in that field just by looking at $_POST['firstname']. Now that's convenient!

Trust No One! Except Me, That Is

There's a big catch. You might design your your form field to accept 40 characters on a single line, but that doesn't prevent users from sending you 41 characters. Or 40,000. On multiple lines. With tabs and backslashes and quotation marks and all sorts of special characters. Naive programmers can get into dangerous trouble this way when they try to pass the user's input to a MySQL database or write it to a nice tab-delimited text file. Suddenly those quotation marks are ending a MySQL expression and starting a new one that deletes your data. And those tabs and newlines are inserting hundreds of extra records into your text file.

So when you receive data from the user, you need to clean it up!

The following PHP function, clean, transforms all kinds of whitespace into single spaces and "escapes" the &, < and > characters so that they don't mess up the HTML of the guestbook page when they are displayed later.

Confused? For more information about declaring and using functions in PHP, see the official PHP tutorial.


function clean($name, $max) {
  # Turn tabs and CRs into spaces so they can't
  # fake other fields or extra entries
  $name = ereg_replace("[[:space:]]", ' ', $name);
  # Escape < > and and & so they
  # can't mess withour HTML markup
  $name = ereg_replace('&', '&amp;', $name);
  $name = ereg_replace('<', '&lt;', $name);
  $name = ereg_replace('>', '&gt;', $name);
  # Don't allow excessively long entries
  $name = substr($name, 0, $max);
  return $name;
}

We also need to undo the work of PHP's "magic quotes" feature, if it is turned on, because we are using a text file rather than a database. Note that magic quotes is also downright dangerous, because it doesn't provide adequate protection for those who are using databases. I present the code that takes care of this in the article "why does PHP insert \ in front of every " in my form data?"

My code doesn't use SQL, so this "clean" function is good enough for my purposes. If you're using SQL, you will also need to clean up quotation marks and several other characters— PHP's "magic quotes" feature does not do the job right. Luckily for you, there's a convenient MySQL PHP function to do it correctly:


$name = mysql_real_escape_string($name);

Now it's safe to use $name in constructing a MySQL query, such as a SELECT query.

So far, so good. But what's the ereg_replace function about? PHP supports "regular expressions," a powerful way to recognize a pattern of characters. ereg_replace allows us to replace every occurrence of that pattern of characters with another string. Here we use it in a very simple way, except for the special pattern [[:space:]], which matches any kind of whitespace (carriage return, line feed, tab, plain old space, et cetera).

Writing to a File

We're ready to write our cleaned-up data to a file. To do that, we'll take advantage of the fopen, fwrite and fclose functions. The most interesting thing here is how we write a line of tab-delimited data to our guestbook data file:


fwrite($file, "$name\t$email\t$comment\n");

The $name, $email and $comment variables are set earlier by fetching them from the $_POST associative array and then cleaning them up with our own clean function. And the $file object comes from a call to fopen. But what you may find odd is that we've put the variable names inside quotation marks, separated by \t and ending in \n.

In PHP, the contents of variables mentioned inside double-quote marks are "interpolated" into the text. The \t sequence is output as a tab. And the \n sequence starts a new line.

Later, when we output the guestbook signatures to the web browser, we'll take advantage of PHP's convenient fgets and split functions to pull these fields back out again.

How To Know When The User Submits The Form

In this example, the guestbook form and the action of the form - the URL that handles the form submission— are the same page, guestbook.php. How is that possible? When we design the guestbook form, we'll give the submit button (an input element with type="submit") the name submit. And when we see that $_POST['submit'] is present, we'll choose to process the form submission. When $_POST['submit'] is not present, we know that the user hasn't entered any form data yet.

Here are the essential bits of guestbook.php that we've discussed. This code works fine, but it's just a bare-bones version. A fully-fledged guestbook should support dates, deleting entries, and so on. Again, you can find code for the complete version in the article how do I make a guestbook for my website?


<html>
<head>
<title>Really Simple PHP Guestbook</title>
</head>
<body>
<h1 align="center">Really Simple PHP Guestbook</h1>
<div align="center">
<table border="0" cellpadding="3" cellspacing="3">
<tr><th>Name</th><th>Email</th><th>Comment</th>
</tr>
<?php
  # Guestbook file will live in the same folder with the page
  $guestbook = 'guestbook.txt';
  # Hide harmless warning messages that confuse users.
  # If you have problems and you don't know why,
  # comment this line out for a while to get more
  # information from PHP
  error_reporting (E_ALL ^ (E_NOTICE | E_WARNING));
  # Process the form submission if there is one
  if ($_POST['submit']) {
    # "a" for append
    $file = fopen($guestbook, "a");
    if (!$file) {
      echo "Can't write to guestbook file";
      die;  
    }
    # Grab the form fields
    $name = $_POST['name'];
    $email = $_POST['email'];
    $comment = $_POST['comment'];
    # Remove dangerous characters, and limit the length
    $name = clean($name, 40);
    $email = clean($email, 40);
    $comment = clean($comment, 40);
    # Write a tab-delimited line to our file
    fwrite($file,
      "$date\t$name\t$email\t$comment\t$id\n");
    fclose($file);  
  }
  # Now we read the file, whether we just added a line or not.
  # 'r' for read
  $file = fopen($guestbook, 'r');
  if ($file) {
    # feof is true at the end of the file, ! means not
    while (!feof($file)) {
      $line = fgets($file);
      $line = trim($line);
      # split returns an array, list re-collates the
      # array into the variables we want  
      list ($name, $email, $comment) =
        split("\t", $line, 3);
      echo "<tr><td>$date</td><td>$name</td>";
      echo "<td>$email</td><td>$comment</td>";
      echo "</tr>\n";
    }
    fclose($file);
  }
  function clean($name, $max) {
    # Turn tabs and CRs into spaces so they can't
    # fake other fields or extra entries
    $name = ereg_replace("[[:space:]]", ' ', $name);
    # Escape < > and and & so they
    # can't mess withour HTML markup
    $name = ereg_replace('&', '&amp;', $name);
    $name = ereg_replace('<', '&lt;', $name);
    $name = ereg_replace('>', '&gt;', $name);
    # Don't allow excessively long entries
    $name = substr($name, 0, $max);
    return $name;
  }
?>
</table>
<form action="guestbook.php" method="POST">
<table border="0" cellpadding="5" cellspacing="5">
<tr>
<td colspan="2">Sign My Guestbook!</td>
</tr>
<tr>
<th>Name</th><td><input name="name" maxlength="40"></td>
</tr>
<tr>
<th>Email</th><td><input name="email" maxlength="40"></td>
</tr>
<tr>
<th>Comment</th><td><input name="comment" maxlength="40"></td>
</tr>
<tr>
<th colspan="2">
<input type="submit" name="submit" value="Sign the Guestbook">
</th>
</tr>
</table>
</form>
</div>
</body>
</html>

Those are the basics! Of course, that's only the tip of the iceberg where PHP is concerned. I strongly recommend that you check out the official PHP tutorial, as well as the Free Webmaster Help PHP/MySQL tutorial.

Using mailto: For Form Submissions (Not Recommended)

It is also possible to receive form submissions by using a mailto: URL as the action attribute of your <form> element.

Unfortunately there are several major disadvantages to mailto:, including:

1. Microsoft Internet Explorer will display a warning to the user, pointing out that submitting a form by email will disclose their email address to the recipient, and asking if they really want to do that.

2. The data won't arrive in your mailbox in a form that's particularly convenient for you to work with.

3. The data doesn't get added to a database.

4. You can't do something in response to the form submission, such as charging a credit card or granting access to part of your website.

Still, if you are using a free hosting service, you might not have any alternatives. I recommend obtaining a quality web host and using PHP. But if that's not an option for you, here is a simple example of a form submission using a mailto: URL:

<FORM METHOD=POST
ACTION="mailto:you@yoursite.com?Subject=Form Submission"
ENCTYPE="text/plain">
<input name="name" value="Your Name"> Age<p>
<input name="food" value="Food Preference"> Food<p>
Your Details:
<p>
<textarea name="details"></textarea>
<p>
<input type=submit value="Send Application Now">
</FORM>

Legal Note: yes, you may use sample HTML, Javascript, PHP and other code presented above in your own projects. You may not reproduce large portions of the text of the article without our express permission.

Got a LiveJournal account? Keep up with the latest articles in this FAQ by adding our syndicated feed to your friends list!