Hrvatski

printer friendly version

Contact form

Contact form is certainly a must-have on your website if you wish to interact with your visitors. By using contact form, there's no need to publish your e-mail address. People can write an e-mail to you without opening a mail client or logging into webmail account.

Basic knowledge of PHP is required in order to understand this tutorial, you can pick up some from my introduction. In this tutorial you will learn how to send data via post method, write custom functions and validate forms.

HTML skeleton of the form

First we have to set up a non-working form with basic fields. You can copy/paste this generic code:

<form action="contact.php" method="post" enctype="multipart/form-data">
	<fieldset>
		<legend>Personal information</legend>
		<label for="name">name</label>
		<input name="name" id="name" type="text" size="50" maxlength="50" />
		<label for="email">e-mail</label>
		<input name="email" id="email" type="text" size="50" maxlength="50" />
		<label for="website">website</label>
		<input name="website" id="website" type="text" size="50" maxlength="50" />
	</fieldset>
	<fieldset>
		<legend>Message</legend>
		<label for="subject">subject</label>
		<input name="subject" id="subject" type="text" size="50" maxlength="50" />
		<label for="message">text</label>
		<textarea name="message" cols="50" rows="5" id="message"></textarea>
	</fieldset>
	<fieldset>
		<input class="button" type="submit" name="send" value="Send message" />
	</fieldset>
</form>

Everything inside the form tag is considered form data, and will be submitted to the script linked in the action attribute — I don't like to separate scripts in more files, and it's easier to avoid misuse this way so entire script will be in a single file I called contact.php. Complex forms with private data should be submitted by post method.

fieldset tag is not required, but since the input element may not be a first-child of the form it's recommended to use it. This tag allows to group thematically related fields. You can see here I grouped personal information and message content. Submit button is inside its own fieldset. You don't have to be a pedant, feel free to use a single fieldset for entire form if it's not complex.

label is used to relate fields with their description. If you click on the description, cursor will be moved to the connected input field — this is especially useful with tiny input fields, like radio buttons and checkboxes. The for attribute says which field is the label attached to.

Finally, we have 2 types of input fields and a textarea which will contain the message content. Fields of type text will be displayed as a single-row text field, submit is displayed like a button which will send the form. There are more types like password, radio, checkbox and hidden which are not required here. textarea is a multi-row input field. Each of the fields has a unique name and id (note the two have the same value, and id should be the same like for in the connected label).

Making the form work

Please note that start of PHP code is marked with <?php and end with ?> — I suppose you know this, so I won't emphasize it later on.

The script consists of 2 main parts: 1) form display and 2) fetching, validating and sending data. How will we know which one should take part? It's the post data. The following condition checks if the post array has been sent, otherwise it will display the contact form:

if(count($_POST) > 0) {
	// send form
} else {
	form_display();
}

Since there is no function named form_display(), we have to write it ourselves. We'll use the HTML mentioned before. A function is defined by a word function followed by its name, brackets containing arguments (if any) and a block of commands.

function form_display() {
	echo '<form action="contact.php" method="post" enctype="multipart/form-data">
		<fieldset>
			<legend>Personal information</legend>
			<label for="name">name</label>
			<input name="name" id="name" type="text" size="50" maxlength="50" />
			<label for="email">e-mail</label>
			<input name="email" id="email" type="text" size="50" maxlength="50" />
			<label for="website">website</label>
			<input name="website" id="website" type="text" size="50" maxlength="50" />
		</fieldset>
		<fieldset>
			<legend>Message</legend>
			<label for="subject">subject</label>
			<input name="subject" id="subject" type="text" size="50" maxlength="50" />
			<label for="message">text</label>
			<textarea name="message" cols="50" rows="5" id="message"></textarea>
		</fieldset>
		<fieldset>
			<input class="button" type="submit" name="send" value="Send message" />
		</fieldset>
		</form>';
	}
}

Copy this function somewhere, preferably on top of your script. Now let's do that send form part.

	$to = '[email protected]';
	$name = stripslashes($_POST['name']);
	$message = stripslashes($_POST['message']);
	$subject = stripslashes($_POST['subject']);
	$email = $_POST['email'];
	$website = $_POST['website'];
	$headers = "From: $name <$email> \r\nReply-To:$email\r\nContent-Type: text/plain; charset=UTF-8\r\nX-Mailer: PHP/".phpversion();
	mail($to, $subject, $message, $headers);

This part assigns posted data to new variables. $to is your e-mail, the one this form will be sent to. stripslashes() function clears extra \ characters from posted data (they are added automatically for safety). Variable $headers stores header information. If it doesn't make any sense to you, don't worry. mail() function merely sends the data to the e-mail adress specified.

If we put these parts together, the script looks like this:

function form_display() {
	echo '<form action="contact.php" method="post" enctype="multipart/form-data">
		<fieldset>
			<legend>Personal information</legend>
			<label for="name">name</label>
			<input name="name" id="name" type="text" size="50" maxlength="50" />
			<label for="email">e-mail</label>
			<input name="email" id="email" type="text" size="50" maxlength="50" />
			<label for="website">website</label>
			<input name="website" id="website" type="text" size="50" maxlength="50" />
		</fieldset>
		<fieldset>
			<legend>Message</legend>
			<label for="subject">subject</label>
			<input name="subject" id="subject" type="text" size="50" maxlength="50" />
			<label for="message">text</label>
			<textarea name="message" cols="50" rows="5" id="message"></textarea>
		</fieldset>
		<fieldset>
			<input class="button" type="submit" name="send" value="Send message" />
		</fieldset>
		</form>';
	}
}
if(count($_POST) > 0) {
	$to = '[email protected]';
	$name = stripslashes($_POST['name']);
	$message = stripslashes($_POST['message']);
	$subject = stripslashes($_POST['subject']);
	$email = $_POST['email'];
	$website = $_POST['website'];
	$headers = "From: $name <$email> \r\nReply-To:$email\r\nContent-Type: text/plain; charset=UTF-8\r\nX-Mailer: PHP/".phpversion();
	mail($to, $subject, $message, $headers);
} else {
	form_display();
}

If you decide to try this script out, it will work. The problem is, it will work even if you don't specify any of the form data.

Form validation

Before we send the data, we should ensure all fields (or at least some) were filled. Otherwise, user should be notified about it and have a chance to fix it.

Make a function validate_form() which will return true in case of sucess, and false (with an error message) in case of failure.

function validate_form($name, $message, $email) {
	if ((empty($name)) || (empty($message)) || (empty($email))) {
		echo 'Error! You didn\'t fill all the required fields (name, e-mail and message).';
		return false;
	} elseif (!eregi('^([._a-z0-9-]+[._a-z0-9-]*)@(([a-z0-9-]+\.)*([a-z0-9-]+)(\.[a-z]{2,3})?)$', $email)) {
		echo 'Error! You didn\'t enter a valid e-mail address.';
		return false;
	} else {
		return true;
	}
}

This function checks if required fields (in my case name, message and e-mail) are empty. If they are not, it checks if e-mail address is entered in a correct format using regular expressions. If any of conditions is true, error message is shown and value false returned, otherwise returned value is true.

We should also make minor modifications to our existing form_display() function, so it can show content of fields that were previously filled.

function form_display($name="", $email="", $website="", $subject="", $message="") {
	echo '<form action="contact.php" method="post" enctype="multipart/form-data">
		<fieldset>
			<legend>Personal information</legend>
			<label for="name">name</label>
			<input name="name" id="name" type="text" value="'.$name.'" size="50" maxlength="50" />
			<label for="email">e-mail</label>
			<input name="email" id="email" type="text" value="'.$email.'" size="50" maxlength="50" />
			<label for="website">website</label>
			<input name="website" id="website" type="text" value="'.$website.'" size="50" maxlength="50" />
		</fieldset>
		<fieldset>
			<legend>Message</legend>
			<label for="subject">subject</label>
			<input name="subject" id="subject" type="text" value="'.$subject.'" size="50" maxlength="50" />
			<label for="message">text</label>
			<textarea name="message" cols="50" rows="5" id="message"> '.$message.'</textarea>
		</fieldset>
		<fieldset>
			<input class="button" type="submit" name="send" value="Send message" />
		</fieldset>
		</form>';
	}
}

With a modification to the sending part:

	$to = '[email protected]';
	$name = stripslashes($_POST['name']);
	$message = stripslashes($_POST['message']);
	$subject = stripslashes($_POST['subject']);
	$email = $_POST['email'];
	$website = $_POST['website'];
	if(validate_form($name, $message, $email)) {
		$headers = "From: $name <$email> \r\nReply-To:$email\r\nContent-Type: text/plain; charset=UTF-8\r\nX-Mailer: PHP/".phpversion();
		mail($to, $subject, $message, $headers);
	} else {
		form_display();
	}

The complete script follows:

<?php
function form_display($name="", $email="", $website="", $subject="", $message="") {
	echo '<form action="contact.php" method="post" enctype="multipart/form-data">
		<fieldset>
			<legend>Personal information</legend>
			<label for="name">name</label>
			<input name="name" id="name" type="text" value="'.$name.'" size="50" maxlength="50" />
			<label for="email">e-mail</label>
			<input name="email" id="email" type="text" value="'.$email.'" size="50" maxlength="50" />
			<label for="website">website</label>
			<input name="website" id="website" type="text" value="'.$website.'" size="50" maxlength="50" />
		</fieldset>
		<fieldset>
			<legend>Message</legend>
			<label for="subject">subject</label>
			<input name="subject" id="subject" type="text" value="'.$subject.'" size="50" maxlength="50" />
			<label for="message">text</label>
			<textarea name="message" cols="50" rows="5" id="message"> '.$message.'</textarea>
		</fieldset>
		<fieldset>
			<input class="button" type="submit" name="send" value="Send message" />
		</fieldset>
		</form>';
	}
}
function validate_form($name, $message, $email) {
	if ((empty($name)) || (empty($message)) || (empty($email))) {
		echo 'Error! You didn\'t fill all the required fields (name, e-mail and message).';
		return false;
	} elseif (!eregi('^([._a-z0-9-]+[._a-z0-9-]*)@(([a-z0-9-]+\.)*([a-z0-9-]+)(\.[a-z]{2,3})?)$', $email)) {
		echo 'Error! You didn\'t enter a valid e-mail address.';
		return false;
	} else {
		return true;
	}
}
if(count($_POST) > 0) {
	$to = '[email protected]';
	$name = stripslashes($_POST['name']);
	$message = stripslashes($_POST['message']);
	$subject = stripslashes($_POST['subject']);
	$email = $_POST['email'];
	$website = $_POST['website'];
	$headers = "From: $name <$email> \r\nReply-To:$email\r\nContent-Type: text/plain; charset=UTF-8\r\nX-Mailer: PHP/".phpversion();
	if(validate_form($name, $message, $email)) {
		mail($to, $subject, $message, $headers);
	} else {
		form_display();
	}
} else {
	form_display();
}
?>

This is it! Copy this script to your contact page and you have a fully working contact form.

Making it pretty

We're done with the scripting part, but something's still itching me. Here's my example stylesheet for this form, feel free to use it and abuse it.

form {
	width: 460px;
	background: #efefef;
	color: #999;
	border: 10px solid #efefef;
	text-align: left;
}
label {
	clear: left;
	float: left;
	width: 100px;
	margin: 6px 0 10px 0;
}
fieldset {
	border: 0;
}
legend {
	display: none;
}
input, select, textarea {
	float: left;
	margin-bottom: 10px;
	width: 340px;
	background: #ccc;
	color: #555;
	border: 2px solid #aaa;
	font: 100% "Arial", "Verdana", "Tahoma", sans-serif;
}
input.button {
	clear: both;
	float: none;
	display: block;
	margin-left:100px;
	width: auto;
	cursor: hand;
	cursor: pointer;
}

Here's the example:

Personal information
Message

I hope you liked and understood this tutorial. Check back for more coding tutorials soon ;)


Share this tutorial with your friends!





My new book is out!

The Human Centered Brand by Nela Dunato


Branding & web design by Nela Dunato

Facebook