Using LAMP

Submitted by martyn on Wed, 08/02/2006 - 20:27

LAMP is the name given to a program stack that is commonly used for developing dynamic web-pages. These applications being the GNU/Linux operating System, Apache webserver, MySQL database and either PHP, Perl or Python.

So what are dynamic web-pages and how do they differ from any other webpage? Web pages can be thought of as either being static or dynamic. Static web-pages are those where the completed document is stored in a file and is merely presented to the client by the webserver. A dynamic page is one whos content is constructed on the fly in response to a request by a client. The basic process thus:

  1. A client connects to a webserver and requests a certain page (which has been written in the form of a script), possibly including form data or other variables with it's request.
  2. The webserver calls the scripting language which constructs a page, utilising the script requested by the client.
  3. Information is requested from the database in the script and is used to fill out the content of the page. The contents of the page may thus change depending on data provided by the client when it makes its request.
  4. The web server then provides this page to the client. The page is then thrown away.

The choice of the PHP pre-processor, Perl or Python Scripting Languages is reasonably arbitrary and I guess will depend as much on which you have experience with or are happiest using. I'm sure there are people that will swear blind that the one that they use if far superior than the others. In this tutorial I will be describing how to use LAMP utilising the PHP pre-processor.

Assumptions

I am going to make a number of assumptions whilst describing how to utilise LAMP:

  • The reader has a basic understanding of HTML.
  • The Apache webserver, MySQL database and PHP are installed, are integrated correctly and running.
  • The reader has sufficient privileges to create files in a directory used by the webserver to serve up web-pages
  • The reader has the ability to at least create tables in a MySQL database.

Though hopefully this tutorial will act as a good reference point from which to gain a greater understanding of how to use LAMP in your own projects, it might be advantageous to at least have a basic understanding of how to write a web-page using basic HTML before reading on.

A very basic address book

Whilst writing this tutorial I will be writing a small address book application, to serve as an example of how to develop using LAMP. The address book will be very basic, capable of storing names with a single telephone number and email address. No error checking will be done to check that the values are correct, though entries will be able to be viewed, added, modified and deleted.

Step 1: Creating the Database

In this tutorial we will be creating the database and table using the commandline applications for MySQL. There are a number of nice front ends available for Linux, such as mysqlcc and more widely in the form of web-based applications such as phpMyAdmin. I have chosen to use the commandline method here for brevity, though if you are considering writing your own pages using LAMP, especially if they have more than one table, I would definitely encourage to look at using one of these applications. If you are to be using webspace and MySQL account on a machine with shared hosting it is unlikely that you will have sufficient privileges to create your own database, as this will require root MySQL access. Though it should be possible to create a table if you have been given access and rights to use a database that has already been setup for you.

Table Design

This could quite easily turn into a tutorial in its own right. Database design is quite a deep topic and can easily be done incorrectly. Since the scope of what this example application is to do is small and reasonably well defined a single simple table will suffice.

The table we are going to create will have 4 columns:

  1. A unique ID

    Though not implicitly needed, providing a unique ID for each field will make it easier to ensure that the correct field is edited, deleted or viewed. This field will be created with the "unique" attribute. This has two effects; two records will not be accepted into the database with the same value and the database will be optimised to search on this field, which should increase the efficiency of our application

  2. Name

    More advanced applications would split the name into at least 2 different fields, making operations such as sorting or searching by first name or surname easier. We will just stick with the one longer text field.

  3. Telephone Number

    Though it might seem sensible to store the telephone as a number, this might not be the best way to store a telephone. Telephone numbers can be formated with non-numerical characters. For instance, especially in the UK, foreign numbers are prefixed with a "+" sign before them and the country code is provided. Other characters such as spaces, dashes and brackets are commonly used in a number of contries to make the number more readable. Thus the telephone number will be stored in a standard text field.

  4. Email Address

    This is quite simple and will be stored in a text field, the hardest decision to make will be the length of the field to use...

Implementing the Database

First we must create a database this can be done using the "mysqladmin" command. Root mysql access is necessary for this, the following command will create a database called 'people':

	$ mysqladmin -u root -p create people
	Enter password:
	$ 
	

It is now necessary to allow the user you wish to access the table as to be able to query and edit the table. To do this log in to mysql as root. This can be achieved using the "mysql" application, a simple commandline interface to mysql databases. If the database server is running locally and allows anonymous access simply running this application with no options will suffice. Hopefully this is not the case, at the very least the daemon will require a username and password for access. If the username is the same as your UNIX username it will be provided automatically, otherwise "-u <your username>" option will be required. To provide a password the "-p" option must be added. The password can then be provided as the username on the commandline, though I would discourage this from being done as it will then be stored in your history file, which could potentially be exploited by intruders into your system. If it not provided you will be prompted to enter it once the application has be called:

	$ mysql -u root -p
	Enter password:
	Welcome to the MySQL monitor.  Commands end with ; or \g.
	Your MySQL connection id is 42 to server version: 4.1.11
	
	Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
	
	mysql> 
	

It should now be possible to give the username you normally use to access the database with all the required rights on the "people" database:

Nb) In mysql not only the username must be specified, but the location that the user is connecting from. This is due to the network aware nature of the database, this tutorial will assume localhost access is used.

	mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
	    -> ON people.*
	    -> TO '<your username>'@'localhost';
	Query OK, 0 rows affected (0.07 sec)
	
	mysql> 
	

You can now quit out if the database as you no longer need root access:

	mysql>quit
	Bye
	$ 
	

It is now necessary to login to the mysql database as your normal user. The name of the database can be provided on the commandline and will be selected for use.

	$ mysql -p people
	Enter password:
	Welcome to the MySQL monitor.  Commands end with ; or \g.
	Your MySQL connection id is 42 to server version: 4.1.11
	
	Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
	
	mysql> 
	

The currently has no tables, as shown by the "show tables" command. It is now time to create a table as outline above. The length for the fields I have chosen are included in the command, in brackets, after the field type:

	mysql> show tables;
	Empty set (0.01 sec)
	
	mysql> CREATE TABLE addr_book (uid SMALLINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, 
	    -> name VARCHAR(30) NOT NULL, phone VARCHAR(20), email VARCHAR(40));
	Query OK, 0 rows affected (0.45 sec)
	
	mysql> show tables;
	+------------------+
	| Tables_in_people |
	+------------------+
	| addr_book        |
	+------------------+
	1 row in set (0.00 sec)
	
	mysql> DESCRIBE addr_book;
	+-------+----------------------+------+-----+---------+----------------+
	| Field | Type                 | Null | Key | Default | Extra          |
	+-------+----------------------+------+-----+---------+----------------+
	| uid   | smallint(5) unsigned |      | PRI | NULL    | auto_increment |
	| name  | varchar(30)          |      |     |         |                |
	| phone | varchar(20)          | YES  |     | NULL    |                |
	| email | varchar(40)          | YES  |     | NULL    |                |
	+-------+----------------------+------+-----+---------+----------------+
	4 rows in set (0.00 sec)
	
	mysql>
	

As shown by the two "show tables" commands, the "CREATE" command has indeed created a table which, although being empty, includes 4 fields. The first is the unique ID, which is setup as the primary key, and thus must be unique. The unique ID is setup to allow autoincrementation, so a value will not need to be calculated for this field when a new row is added. It is also given type unsigned small integer, which can hold values from 0 to 65535, which should be enough ;-). The other three fields are of type "VARCHAR" (a field which may have a varying number of characters, up to the set maximum), called name, phone and email. The "name" field is set so as not to be allowed to be empty, or null. This is to ensure all items in the database have a name with which a human could recognise the record.

An initial entry

In order to check that first script we will write, the view script, is operating correctly we will now place a test record into the mysql database. This is done using the "INSERT" command:

	mysql> INSERT INTO `addr_book` SET `name`='Test Name' , `phone`='01234 567890' , 
	    -> `email`='test@no.domain.yet';
	Query OK, 1 row affected (0.31 sec)
	
	mysql> SELECT * FROM addr_book;
	+-----+-----------+--------------+--------------------+
	| uid | name      | phone        | email              |
	+-----+-----------+--------------+--------------------+
	|   1 | Test Name | 01234 567890 | test@no.domain.yet |
	+-----+-----------+--------------+--------------------+
	1 row in set (0.01 sec)
	
	mysql> 
	

We are now ready to start coding a PHP web-page.

Step 2: Coding a webpage using PHP

What PHP is and isn't

Developing web-pages using PHP is slightly different from how one would go about developing dynamic web-pages in other languages. It is possible to write a dynamic page in most languages, by creating an app or script which outputs HTML formatted text to the standard output, even C can be used. This application is then placed in the webservers cgi-bin. PHP is a little different in this regard. PHP is not a normal scripting language, it is a Pre-processor language and as such can be written in-line in a HTML document. HTML documents are then scanned before being sent to the client and any PHP scripting included is run before being sent to the client. A page containing PHP can also be thought of as a script with HTML written in-line as any HTML blocks in PHP loops will we written out each time the loop is traversed. This combined HTML/script is not placed in the cgi-bin, it is placed in the HTML directory of the webserver. It is possible to start of with a static page and add PHP scripting to it, however it is necessary to change the file the extension ".php".

An initial static page

First we shall write a very simple static page, with the layout to hold our address book entries. We shall call this page "index.php" and will be called by default when a client asks for the directory to be returned. I have created a directory under the main Apache HTML directory called people and the file is saved there.

<html>
	<head>
		<title>Address Book</title>
	</head>
	<body>
		<h1>Address Book</h1>
		<table border="1">
			<tr>
				<td>Name</td>
				<td>Telephone Number</td>
				<td>Email</td>
			</tr>
			<tr>
				<td></td>
				<td></td>
				<td></td>
			</tr>
		</table>
	</body>
</html>

Listing for index.php

view of index.php

This page has a title and a blank row, however, no data and is still very static. The first step I am going to make is to place a PHP loop structure in. For now this will just loop on a count varable and allow me to create an arbitrary number of rows in with dummy data. Later this loop will allow me to construct a row for each record returned from the database.

<html>
	<head>
		<title>Address Book</title>
	</head>
	<body>
		<h1>Address Book</h1>
		<table border="1">
			<tr>
				<td>Name</td>
				<td>Telephone Number</td>
				<td>Email</td>
			</tr>
<?php
$count = 0;
while($count < 5){
?>
			<tr>
				<td><?php echo "name$count"; ?></td>
				<td><?php echo "phone$count"; ?></td>
				<td><?php echo "email$count"; ?></td>
			</tr>
<?php
	$count++;
}
?>
		</table>
	</body>
</html>

Listing for index.php

view of index.php

The above example introduces 5 important topics; the PHP tags; the syntax, variables; a loop example (in this case the while loop) and "echo" output function. I will cover these before moving on.

As you can see there are a few small blocks of PHP scattered through the script, which started of in the previous example without any PHP code in it. These blocks are started with the "<?php" tag and ended with "?>". As this example shows, it is not important for even the entirety of a loop structure to be confined to a single code block, as shown by the placement of the "{" and "}" brackets. The tags can be opened and closed within the HTML just to insert single lines, as with the "echo" commands.

The syntax should look quite familiar to anyone who is used to writting C code. There are instances where this is not the case, such as with the "echo" statement, where the parenthesis don't need to be used, though they can be if it is so wished. It must also be noted that each line is ended by the use of a semi-colon (as is also the case in C).

Unlike C, variables do not have to be declared, however they must start with a dollar sign. As can be seen in there use in the "echo" commands, they maybe used inside quotes and will still be converted to the value they contain.

The while construct causes the subsequent line to be repeatedly executed, until the statement included the the brackets. If the construct is followed by a block, denoted by curly brackets, then the entire block is repeated. For example "while($x<1) $x=2;" would only loop once, in the first execution x would be given the value 2 and hence the statement "$x<1" would be false. Of course this is only the case as long as x was less that 1 to begin with, else the statement "$x=2;" would never be executed. Another example "while(1);" would lock the program into a never ending loop! Since values greater that 0 are considered to be true and values less than 1 false. It would also not do any further useful work as the construct is completed with a semi-colon and thus the code to be executed whilst the statement is true is null.

Lastly this short piece of code introduces the "echo" command. This command is very useful and allows simple strings to be output. Variables can be included as shown in the example above, however the formating capabilities are fairly limited. PHP does however include a "printf" command that is comparable to the function of the same name in C and thus has much greater formatting capabilities, such as to limit the number of decimal places to which a number is shown.

Step 3: Retrieving records from the database

We now have a database, with a record in it, waiting for us to retrieve it. As show at the end of step 1, it is possible to retrieve information stored in the database using the "SELECT" command. This is an SQL statement and we can use them from PHP as well as from the mysql application. The one used returns all fields of all records in the addr_book table.

For the main page of our address book we want to pull back the names, email addresses and phone numbers of each entry. SQL is quite a complex language with many options and again, could be considered a tutorial in it's own right. Here we introduce the first of the basic commands that we will cover, the "SELECT" command. There is quite a bit of information in the documentation at "www.mysql.com" and there is quite a large info section (which may already be installed on your computer - just type "info mysql"). When writing SQL statements it is usual for the language portions of the statement to be written in capitals. The very basic syntax for the "SELECT" statement is "SELECT <fields> FROM <table> WHERE <case-to-meet>", there are many other options which I will not go into now. To pull back just the two fields we require, we use the statement "SELECT `name`,`email`,`phone` FROM `addr_book`". Notice that this doesn't have a "WHERE" clause, this is not needed because we want all the records.

Now that we have an SQL statement to use we need to get to the point where we can use it. In PHP this means opening a connection to the MySQL server, selecting the database that you wish to use. That connection can then be used to make the query, the result can then be parsed (after all we want to know the information returned from the query) and finally closing the connection. This can be seen in action in the code listing below:

<?php
// Open a connection to the mysql server
$connection = mysql_connect("localhost","<your username>","<your password>") 
	or die("Can not connect to database.");

?>
<html>
	<head>
		<title>Address Book</title>
	</head>
	<body>
		<h1>Address Book</h1>
		<table border="1">
			<tr>
				<td>Name</td>
				<td>Telephone Number</td>
				<td>Email</td>
			</tr>
<?php


// Select database
$db = mysql_select_db("people", $connection) or die("Can't select database.");

// Send query and save result
$result = mysql_query("SELECT `name`,`email`,`phone` FROM `addr_book`", $connection) 
	or die("Can't query table.");

$count = 0;

// Loop for each row, placing record data in associative array

while($row = mysql_fetch_assoc($result) $count < 5){
?>
			<tr>
				<td><?php echo $row["name"]; "name$count"; ?></td>
				<td><?php echo $row["phone"]; "phone$count"; ?></td>
				<td><?php echo $row["email"]; "email$count"; ?></td>
			</tr>
<?php
	$count++;
}
// Close connection
mysql_close();
?>
		</table>
	</body>
</html>

Listing for index.php

view of index.php

Aside from the functions, which are commented in line, this example shows the use of an associative array. This type of array allows each field to be identified by a unique string rather than the usual numeric value. This can be seen where the name, phone number or email address is added to the page:

$row["name"]

It is also possible to use standard arrays, "mysql_fetch_array()" will return the items in a standard array in the order they are specified in the first portion of the SELECT SQL query.

You may also have noticed that the first few commands also have an 'or die("string");' function attached to the end. This function is called if the function it is attached to fails. The die function stops the running of the script, returning the error message provided. This is important so as to stop the script attempting to create any more of the page when it has been impossible to connect to the mysql server, database or the query has not been valid.

Step 4: Editing and Deleting Records

In the previous section we wrote a page that could query the MySQL database and display the results. This gets us a little closer to a functioning address book. The last two things to do are create a further 2 scripts to add/edit entries and delete entries. This will also require a few changes to the script we have written above.

Adding or Editing Entries

There are two steps required to add or edit a page. The first step is it input or alter the current data, the second is to save it into the database. The simplest way to do this is to use two scripts. The first will take the ID that the user wishes to edit, if this is set to "new" it will not try and get the data from the database and instead display a blank form. This page will have an HTML form embedded into it, which when a button is activated with send the data onto a second script which will format the data, determine whether it is a new entry or an edited entry and take the required action. It is also necessary to make a few more changes to the index page so that the user has links to edit and add entries.

<?php
// Open a connection to the mysql server
$connection = mysql_connect("localhost","<your username>","<your password>") 
	or die("Can not connect to database.");

?>
<html>
	<head>
		<title>Address Book</title>
	</head>
	<body>
		<h1>Address Book</h1>
		<table border="1">
			<tr>
				<td>Name</td>
				<td>Telephone Number</td>
				<td>Email</td>
				<td>Action</td>
				
			</tr>
<?php

// Select database
$db = mysql_select_db("people", $connection) or die("Can't select database.");

// Send query
$result = mysql_query("SELECT * FROM `addr_book`", $connection) or die("Can't query table.");

// Loop for each row, placing record data in associative array
while($row = mysql_fetch_assoc($result)){
?>
			<tr>
				<td><?php echo $row["name"]; ?></a></td>
				<td><?php echo $row["phone"]; ?></td>
				<td><?php echo $row["email"]; ?></td>
				<td><a href="<?php echo "edit.php?ID=" . $row["uid"]; ?>">edit</a></td>
			</tr>
<?php
}

// Close Database
mysql_close();
?>
		</table>
		<a href="edit.php?ID=new">Add Record</a>
	</body>
</html>

Listing for index.php

view of index.php

As you can see above, three lines are added to index.php. The first of these lines adds an extra column heading to the table, the second adds a hyperlink to each column to allow editing. The URL contains a variable which is the uid for the entry in the MySQL database. This is past via the "get" method to the "edit.php" script. The last of these lines has a similar effect to the second, but rather that passing a unique ID, it passes the string "new". As well will see in a minute, this causes the edit script to add a new entry rather than edit an existing one.

<?php

// Read GET data to find ID to edit
$ID = $_GET["ID"];

if(trim($ID) != "new"){
	
	// Open a connection to the mysql server
	$connection = mysql_connect("localhost","<your username>","<your password>") 
		or die("Can not connect to database.");
	
	// Select database
	$db = mysql_select_db("people", $connection) or die("Can't select database.");
	
	// Send query
	$result = mysql_query("SELECT * FROM `addr_book` WHERE `uid` = '$ID'", $connection) 
		or die("Can't query table.");
	
	// Get data into associative array
	$row = mysql_fetch_assoc($result);
}
	
?>
<html>
	<head>
		<title>Address Book - Edit</title>
	</head>
	<body>
		<h1>Edit Entry</h1>
		<form method="GET" action="submit.php">
		<input type="hidden" name="uid" value="<?php echo $ID;?>">
		<table border="1">
			<tr>
				<td>Name</td>
				<td><input name="name" value="<?php echo $row["name"]; ?>"></td>
			</tr>
			<tr>
				<td>Telephone Number</td>
				<td><input name="phone" value="<?php echo $row["phone"]; ?>"></td>
			</tr>
			<tr>
				<td>Email</td>
				<td><input name="email" value="<?php echo $row["email"]; ?>"></td>
			</tr>
<?php

if(trim($ID) != "new"){
	
	// Close Database
	mysql_close();
	
}

?>
		</table>
		<input type="submit" name="submit" value="OK" />
		</form>
	</body>
</html>

Listing for edit.php

view of edit.php

The edit script, first accepts the variable sent to it in the URL. PHP provides to arrays, "$_GET[]" and "$_POST[]" for the two standard methods for transmitting data back to the server. As can be seen in the example this can me accessed as an associative array, using the variable name. The script then checks, using the "if" statement, to see if the variable has been sent with the value "new", if not it makes a connection to the MySQL database. This is not required if a new record is wanted and the page just displays empty fields. These fields are given a name and if an existing record has been chosen, the value of the matching field in the MySQL database. The fields are contained in a form. When the "submit" input is activated, the current values in the fields are past, attached to the URL, to the script given in the "action" variable in the form tag, in this case "submit.php".

<?php

// Read GET data to find ID to edit
$uid = trim($_GET["uid"]);
$name = trim($_GET["name"]);
$phone = trim($_GET["phone"]);
$email = trim($_GET["email"]);

// Open a connection to the mysql server
$connection = mysql_connect("localhost","<your username>","<your password>") 
	or die("Can not connect to database.");

// Select database
$db = mysql_select_db("people", $connection) or die("Can't select database.");

// Check name exists
if($name !="") $valid=1;
else $valid=0;

if($valid == 1){

	if($uid == "new"){
		// Build Query
		$query = "INSERT INTO `addr_book` SET `name`='$name' , `phone`='$phone' , `email`='$email'";
	}else{
		// Build Query
		$query = "UPDATE `addr_book` SET `name`='$name' , `phone`='$phone' , `email`='$email' WHERE `uid`='$uid'";
	}
	// Send query
	$result = mysql_query($query, $connection) or die("Can't query table.");
}

// Close Database
mysql_close();

?>
<html>
	<head>
		<title>Address Book - Submit</title>
	</head>
	<body>
		<h1>Submit Entry</h1>
<?php
if($valid == 1){
?>
		<p>Submission has been successfull.</p>
<?php
}else{
?>
		<p>Submission has been unsuccessful.</p>
<?php
}
?>
		<a href="index.php">Back to address book</a>
	</body>
</html>

Listing for submit.php

view of submit.php

Last of all we have the submit script. This script starts of very similar to the edit script, the variables are collected and trimmed, this removes any white space. A connection is then opened to the database and the validity of the name field is checked to ensure it is not empty. This is necessary as you may remember from the "name" field in the database is necessary. If it is valid an "INSERT" or "UPDATE" statement is constructed, depending on whether the uid is defined or set to "new". Since the database is set to auto-increment the unique ID it is not explicitly set in the insert statement, the MySQL database automatically takes care of this. The SQL statement that has just been constructed is sent to the MySQL server. The last step is to construct a page to send back to the user. This page is set to either display different messages depending on whether the submission was ultimately a success or not.

Deleting Entries

The delete functionality is just shown here for completeness, the only new thing that it shows is the "DELETE" SQL statement. First another change is required to the index page.

<?php
// Open a connection to the mysql database
$connection = mysql_connect("localhost","<your username>","<your password>") 
	or die("Can not connect to database.");

?>
<html>
	<head>
		<title>Address Book</title>
	</head>
	<body>
		<h1>Address Book</h1>
		<table border="1">
			<tr>
				<td>Name</td>
				<td>Telephone Number</td>
				<td>Email</td>
				<td>Action</td>
				
			</tr>
<?php

$db = mysql_select_db("people", $connection) or die("Can't select database.");

// Send query
$result = mysql_query("SELECT * FROM `addr_book`", $connection) or die("Can't query table.");

while($row = mysql_fetch_assoc($result)){
?>
			<tr>
				<td><?php echo $row["name"]; ?></a></td>
				<td><?php echo $row["phone"]; ?></td>
				<td><?php echo $row["email"]; ?></td>
				<td><a href="<?php echo "edit.php?ID=" . $row["uid"]; ?>">edit</a> 
				<a href="<?php echo "delete.php?ID=" . $row["uid"]; ?>">delete</a></td>
			</tr>
<?php
//	$count++;
}

// Close Database
mysql_close();
?>
		</table>
		<a href="edit.php?ID=new">Add Record</a>
	</body>
</html>

Listing for index.php

view of index.php

As you can see this just adds an extra URL to the new "action" column and is very similar to that used to edit, just calls the delete script.

<?php

// Read GET data to find ID to edit
$uid = $_GET["ID"];

// Open a connection to the mysql server
$connection = mysql_connect("localhost","<your username>","<your password>") 
	or die("Can not connect to database.");

// Select database
$db = mysql_select_db("people", $connection) or die("Can't select database.");

// Send query
$result = mysql_query("DELETE FROM `addr_book` WHERE `uid` = '$uid'", $connection) 
	or die("Can't query table.");

// Close Database
mysql_close();

?>
<html>
	<head>
		<title>Address Book - Delete</title>
	</head>
	<body>
		<h1>Delete Entry</h1>
		<p>Entry Deleted.</p>
		<a href="index.php">Back to address book</a>
	</body>
</html>

Listing for delete.php

view of delete.php

As with the edit script the "GET" data is collected; a connection to the database is made; the database connection is closed and a basic page returned to the user. In this case the "DELETE" statement is used, which in this case simply removes records with a matching unique ID, which by it's very nature should remove just one row. This could be explicitly set by appending "LIMIT 1" to the SQL statement, but this is not necessary.

Conclusions

This completes the address book, providing the functionality to view, add, edit and remove records; which consist of a name plus optional phone number and/or email address. Though this script functions there are a number of additions that I would make to it before using it. The most obvious thing is error checking. This was touched on with the validity check on the name field, though there are many places when more checking is necessary, such as checking the email address and phone number at least have a valid structure. Any data sent between scripts should be checked to ensure that the values haven't been crafted to cause dangerous errors in the scripts as a malicious attack.

There are many features and improvement that could also be added quite easily. The layout could be greatly improved, the HTML used here is very simple. Features such as crafting a "mailto" URL around the email address, thus allowing users to simple click on the email address, on a properly setup computer, to send an email address. Many other additions can be imagined, the sky is the limit and small features can be added and added only limited by your understanding and creativity.

The languages covered here are done so in a very basic manner. There is much more to be learnt about each of them, there are many books and websites that cover them in more detail. For HTML take a look at the w3c website. Please remember to write following w3c web standards, these standards allow your creations to be usable by the maximum number of people and should ensure that they are accessable long after they are written. The Apache webserver is provided by the Apache Software Foundation. PHPs main site provides a wealth of knowledge about PHP. Finally the MySQL database is provided by MySQL AB and there is a wealth of documentation available, with user comments, on their site.

I hope that you have found this tutorial useful all the examples given here can be downloaded as a zip file steps.zip. All that it leaves me to do is it wish you the greatest luck writing your own pages!