All web developers will at some point need to program their own form. Whether it is for database submission, emailing, or for some other purpose, forms represent the primary means of enabling a user to send data to an application. As a result, it is important to have control over the data collected by your forms, which will aid in the creation of streamlined, error-free applications.

Assumptions

This article assumes the reader has some prior knowledge of object-oriented design and/or programming.

Why Validate Forms Server-Side?

Many forms out there today are surprisingly validated with JavaScript (the client-side approach). However, there is one potential problem: what if the user has JavaScript disabled? Some sources indicate as many as 10% of users do. Not only will this open your application up to receiving poorly formatted data, but there are security issues as well. The reason for using server-side validation is simple, all data that is submitted through the form is capable of being validated, regardless of any options that are disabled on a user's browser.

Application Design

A modular approach to a design such as this will be crucial for the application's success. Regardless of what you may hear, you should not write a line of code without thoroughly planning out your design. A good technique will usually result in about 70% of your time spent on design (and diagrams) with the remaining 30% on programming. It will be a good step if you can draw out how your application will function, and be able to explain it to others.
So where should we start? We need to design a core object first. In this case we will call it a ValidationSet. As the name hints, our ValidationSet will store all of our form Validators. Each Validator will determine if the data passed was valid according to its own set of rules. If the data is invalid, we will need to return a ValidationError object to our ValidationSet.
There is one important thing to note here, object names such as "Validators" should never be plural. This is a hint that there is more involved than just making one object. We will need to develop all kinds of validator objects and while they will be specific to what kind of validation purpose they serve, they will all need to be added to a single ValidationSet. Object-oriented theory tells us that we should therefore use a superclass. The reason for this is that our ValidationSet can be coded to expect a single type of object (Validator in this case), which gives a layer of abstraction between the object representing the form validation as a whole and the objects doing the actual work. Those of you familiar with design patterns may recognize this as ‘code to an interface, not an implementation’. Objects such as an EmailValidator or PhoneValidator are examples of different types of form validators we may require. Figure 1.1 shows us what the overall validation system may look like drawn out:

Object Diagrams

Now that we have our overall application thought out, we can continue with diagramming our individual objects. If you haven't dealt with object diagramming before that's okay. Diagramming is a simple task where you come up with all your objects and the methods they will contain. Although there are several programs out there that will help you diagram, I prefer the old pencil and paper approach.
We will begin with diagramming the ValidationSet object. Since the ValidationSet will be storing all of our validators and ValidationErrors, we will need methods to add them. We must also be able to invoke a method which will tell all of the stored validators to perform their individual validations. Furthermore, we will need to know if the application has found any errors, and provide methods for returning a single error, or all of them. Another good thing to plan for is allowing our validators the capability to run validations against a database. Rather than storing a database object in each individual validator, we can just store it once in our ValidationSet. As a result, we will need methods to get and set our database connection object as well. Gathering this information, we can draw out an object diagram for our ValidationSet similar to that shown in Figure 2.1:

We will continue on with diagramming our Validator superclass. It is important to identify methods that all Validator objects will inherit. Since our ValidationSet object stores all of our errors (and each Validator must be capable of sending it an error), we will need a way to access that object’s methods by using a reference. This reference will also give our validators the ability to retrieve the database connection object mentioned above. All of our validators must also be able to retrieve a form field’s submitted value (the actual form field’s name will be sent individually to each Validator’s constructor). These two methods will comprise our Validator object as shown in Figure 2.2:

Specific validators, such as our EmailValidator will be simple in their design. They will be limited to a constructor and a validate method. Remember, because these objects will extend our Validator object, they will inherit those methods as well. Figure 2.3 shows us what a specific validator will look like:

If an error is found, a ValidationError will be instantiated from a specific validator object (in the validate method mentioned above), and then sent to the ValidationSet. It will comprise both a field name and an error message associated with that field. As a result, this object will contain both a method for retrieving the field name, and another for the error message, as shown in Figure 2.4:

The Code

ValidationSet:  Since all of our classes have been diagrammed, an experienced object-oriented PHP programmer will breeze through this step. Although we will try to focus on the code of the more complicated object methods, let’s take a quick look at the simpler methods of the ValidationSet class:
function ValidationSet($a_obj_DBConn = null)
	{
		$this->arr_validators = array();
		$this->arr_validationErrors = array();
		$this->obj_DBConn = $a_obj_DBConn;
		$this->bool_hasErrors = false;
	}

	
	function setDBConn($a_obj_DBConn)
	{
		$this->obj_DBConn = $a_obj_DBConn;
	}

	function getDBConn()
	{
		return $this->obj_DBConn;
	}
	
	
	function addValidator($a_obj_validator)
	{
		$a_obj_validator->setValidationSet(&$this);
		array_push($this->arr_validators, $a_obj_validator);
	}
	
	function addValidationError($a_obj_validationError)
	{
		array_push($this->arr_validationErrors, $a_obj_validationError);
		$this->setHasErrors(true);
	}

	function hasErrors()
	{
		return $this->bool_hasErrors;
	}
	
	
	function setHasErrors($a_bool_hasErrors)
	{
		$this->bool_hasErrors = $a_bool_hasErrors;
	}
Next we will look at the getErrors method. This method will essentially return an array of ValidationError objects. The complexity increases however, when we allow a parameter to dictate if each field should return multiple errors or just a single error. If we want to return just a single error for each field, we will use a for loop to search through each ValidationError. An IF statement will make sure we only add the error to the returned array if the field name is unique. Here’s the code:
	function getErrors($a_bool_allowMultipleErrors = false)
	{
		$arr_returnedErrors = array();
		$arr_fieldNames = array();
		
		if($a_bool_allowMultipleErrors)
		{
			$arr_returnedErrors = $this->arr_validationErrors;
		}
		else
		{
			for($i = 0; $i < sizeof($this->arr_validationErrors); $i++)
			{
				if(!in_array($this->arr_validationErrors[$i]->getFieldName(), $arr_fieldNames))
				{
					array_push($arr_fieldNames, $this->arr_validationErrors[$i]->getFieldName());
					array_push($arr_returnedErrors, $this->arr_validationErrors[$i]);
				}
			}
		}
		return $arr_returnedErrors;
	}
Our getErrorByFieldName method will also use a for loop to search through each ValidationError. We will check each ValidationError’s field name. If this field name matches the one passed as the parameter, the ValidationError is returned.
	function getErrorByFieldName($a_str_fieldName)
	{
		for($i = 0; $i < sizeof($this->arr_validationErrors); $i++)
		{
			if($this->arr_validationErrors[$i]->getFieldName() == $a_str_fieldName)
			{
				return $this->arr_validationErrors[$i]->getErrorMessage();
			}
		}
	}
The final method, validate, will loop through each of the stored validators. Inside this loop, we will call the validate method on each specific Validator object. Each of the specific validators will send back ValidationErrors accordingly.
	function validate()
	{
		for($i = 0; $i < sizeof($this->arr_validators); $i++)
		{
			$obj_validator = $this->arr_validators[$i];
			$obj_validator->validate();
		}
	}

Validator

The setValidationSet method can be written in one line. The most important thing to note here is that the ValidationSet parameter is passed by reference, and not by value. This method will allow each specific validator to access the ValidationSet’s methods. This will be important when we want to send a ValidationError back to the ValidationSet.
	function setValidationSet(&$a_obj_validationSet)
	{
		$this->obj_validationSet =& $a_obj_validationSet;
	}
Our second method, getValueByFieldName will use a foreach loop to search through all GET/POST variables. It will return the value of the variable that has the same name as what was passed as a parameter to the method.
	function getValueByFieldName($a_str_fieldName)
	{
		foreach($_REQUEST as $key => $value)
		{
		   if(strtolower($key) == strtolower($a_str_fieldName))
		   {
		   	return $value;
		   }
		}
	}
EmailValidator
Let’s take a look at the constructor here, as it will be a bit more complex than the other classes’ constructors. An IF statement will check and see if a field value was passed as a parameter, If it wasn’t, we are essentially telling the class to go ahead and search through all the GET/POST variables and find it automatically. Another IF statement will allow the class to have a default error message return if one wasn’t passed as a parameter. Here’s the code:
	function EmailValidator($a_str_fieldName, $a_str_errorMessage = null, $a_str_fieldValue = null)
	{
		$this->str_fieldName = $a_str_fieldName;
		$this->str_fieldValue = $a_str_fieldValue;
		
		if($this->str_fieldValue == null)
		{
			$this->str_fieldValue = $this->getValueByFieldName($this->str_fieldName);
		}

		if($a_str_errorMessage == null)
		{
			$this->str_errorMessage = "Invalid e-mail address";
		}
		else
		{
			$this->str_errorMessage = $a_str_errorMessage;
		}
	}
The validate method for this class will use RegEx to check for a valid email address. We should also take into consideration that we probably shouldn’t validate the email address if it is blank (a different type of Validator should check for this).
	function validate()
	{
		if(strlen($this->str_fieldValue) != 0)
		{
			if (!eregi('^[A-Z0-9._%-]+@[A-Z0-9._%-]+\.[A-Z]{2,6}$', $this->str_fieldValue))
			{
				$this->obj_validationSet->addValidationError(new ValidationError($this->str_fieldName, $this->str_errorMessage));
			}
		}
	}

ValidationError

	function ValidationError($a_str_fieldName, $a_str_errorMessage)
	{
		$this->str_fieldName = $a_str_fieldName;
		$this->str_errorMessage = $a_str_errorMessage;
	}
	
	function getFieldName()
	{
		return $this->str_fieldName;	
	}
	
	
	function getErrorMessage()
	{
		return $this->str_errorMessage;	
	}

Implementation

Implementation of the system is fairly easy. We will begin with our PHP code which will precede our HTML. We will instantiate a ValidationSet, and check if the HTML form has been submitted. If submission has occurred, we will attach and run our Validator. If no errors are found, we will then be permitted to store the form data. Here’s an example using the EmailValidator:
	require_once('_includes/classes/validation/ValidationSet.php');
	
	$obj_validationSet = new ValidationSet();
	
	if($_POST['submitted'] == 'yes')
	{
		$obj_validationSet->addValidator(new EmailValidator('email'));
		$obj_validationSet->validate();
		
		if(!$obj_validationSet->hasErrors())
		{
			// store form data here
			// exit the page
		}
	}

The example HTML form will be simple as well. We will have one field called “email” that will submit as a POST variable. Should this field contain an error; the user will be notified by the getErrorByFieldName output.
	<html>
	<body>
	<form action="index.php" method="POST">
		<input type="hidden" name="submitted" value="yes" />
		<input type="text" name="email" value="<?=$_POST['email']?>" /><?=$obj_validationSet->getErrorByFieldName('email')?><br /><br />
		<input type="submit" value="submit" />
	</form>
	</body>
	</html>

Conclusion

Forms represent the primary means of enabling a user to send data to an application. Valid data will aid in the creation of streamlined, error-free applications. As a result, the need for a stable and modular form validation system is on the rise.
This system was designed the way it is, so that everyone can develop their own validators without affecting the core of the application. To save all of you some time however, I have made available a fully-documented open-source version of this system, you may download it here. I hope all of you have found this article informative, and have a newly grown respect for object-oriented development. Happy coding!