One of the most common and time consuming tasks in web application development is also one of the most important. Input validation. This class encapsulates the validation to keep it in one place and out of your page handling code.

The basic validation checks are based on a class by Nick Geller.

<?php
class Validator
{
    private 
$_fields = array();    /* field objects */
    
private $_errors = array();    /* errors returned by the validation routine */
    
private $_isValid;             /* valid flag*/

    
public function __construct($fields=array())
    {
        
$this->_fields $fields;
    }

    public function 
addField($field)
    {
        
$this->_fields[] = $field;
    }

    public function 
validate()
    {
        
$this->_isValid true;
        foreach(
$this->_fields as $currField)
        {
            
$currName $currField->getName();
            
$currValue $currField->getValue();
            
$currRuleset $currField->getRules();

            foreach (
$currRuleset as $currRule)
            {
                
$currValid true;
                
$currRuleType $currRule->getType();
                
$currRuleTest $currRule->getTest();
                
$currRuleErrMsg $currRule->getMsg();
                
$field_string_size strlen($currValue);

                switch(
$currRuleType)
                {
                    case 
"maxlength":
                        
/* field is greater than maximum allowed lenth */
                        
if($field_string_size $currRuleTest)
                        {
                            
$currValid false;
                            
$this->_isValid false;
                        }
                        break;
                    case 
"minlength":
                        
/* field is less than minimum required lenth */
                        
if($field_string_size $currRuleTest)
                        {
                            
$currValid false;
                            
$this->_isValid false;
                        }
                        break;
                    case 
"length":
                        
/* field is does not equal to required lenth */
                        
if($field_string_size != $currRuleTest)
                        {
                            
$currValid false;
                            
$this->_isValid false;
                        }
                        break;
                    case 
"match":
                        
/* field does not match a required value */
                        
if($currValue != $currRuleTest)
                        {
                            
$currValid false;
                            
$this->_isValid false;
                        }
                        break;
                    case 
"not":
                        
/* fields value is not acceptable */
                        
if($currValue == $currRuleTest)
                        {
                            
$currValid false;
                            
$this->_isValid false;
                        }
                        break;
                    case 
"alpha":
                        
/* only alphabetical characters are required for this field */
                        
if(!eregi("^[a-zA-Z ]+$"$currValue))
                        {
                            
$currValid false;
                            
$this->_isValid false;
                        }
                        break;
                    case 
"numeric":
                        
/* only numeric characters are required for this field*/
                        
if(!eregi("^[0-9]+$"$currValue))
                        {
                            
$currValid false;
                            
$this->_isValid false;
                        }
                        break;
                    case "gt":
                        
/* field does not contain a required character */
                        
if($currValue <= $currRuleTest)
                        {
                            
$currValid false;
                            
$this->_isValid false;
                        }
                        break;
                    case 
"lt":
                        if (
$currValue >= $currRuleTest)
                        {
                            
$currValid false;
                            
$this->_isValid false;
                        }
                        break;
                    case 
"email":
                        
/* fields value is not acceptable */
                        
if(!preg_match("/^s*[^@ rnt#$%;]+@[^@ rnt#$%;]+.w{2,3}s*$/"$currValue))
                        {
                            
$currValid false;
                            
$this->_isValid false;
                        }
                        break;
                }
                if (!
$currValid)
                {
                    
$this->_errors[$currName][] = $currRuleErrMsg;
                }
            }
        }
        return 
$this->_isValid;
    }

    function 
getErrors()
    {
        return 
$this->_errors;
    }
}

class 
Field
{
    private 
$_name;
    private 
$_value;
    private 
$_rules = array();

    public function 
__construct($name,$value=null)
    {
        
$this->_name $name;
        
$this->_value $value;
    }

    public function 
addRule($rule)
    {
        
$this->_rules[] = $rule;
    }

    public function 
getName()
    {
        return 
$this->_name;
    }

    public function 
getValue()
    {
        return 
$this->_value;
    }

    public function 
getRules()
    {
        return 
$this->_rules;
    }

    public function 
setValue($value)
    {
        
$this->_value $value;
    }
}

class 
Rule
{
    private 
$_type;
    private 
$_test;
    private 
$_msg;

    public function 
__construct($type$test$msg)
    {
        
$this->_type $type;
        
$this->_test $test;
        
$this->_msg $msg;
    }

    public function 
getType()
    {
        return 
$this->_type;
    }

    public function 
getTest()
    {
        return 
$this->_test;
    }

    public function 
getMsg()
    {
        return 
$this->_msg;
    }
}

//Rule Constants
define("VALIDATE_MAXLENGTH""maxlength");
define("VALIDATE_MINLENGTH""minlength");
define("VALIDATE_LENGTH","length");
define("VALIDATE_MATCH","match");
define("VALIDATE_HAS","has");
define("VALIDATE_NOT","not");
define("VALIDATE_IN","in");
define("VALIDATE_ALPHA","alpha");
define("VALIDATE_NUMERIC","numeric");
define("VALIDATE_LESSTHAN""lt");
define("VALIDATE_GREATERTHAN""gt");
define("VALIDATE_EMAIL","email");


Usage:
$validator = new Validator();

$nameField = new Field('name'$request->getParameter('name'));
$nameField->addRule(new Rule(VALIDATE_MINLENGTH1"Please enter you Name"));
$nameField->addRule(new Rule(VALIDATE_MAXLENGTH128"Name may not contain more than 128 chars"));
$validator->addField($nameField);

$emailField = new Field('email'$request->getParameter('email'));
$emailField->addRule(new Rule(VALIDATE_EMAILnull"Please enter a valid email address"));
$emailField->addRule(new Rule(VALIDATE_MAXLENGTH128"Email may not contain more than 128 chars"));
$validator->addField($emailField);

if (
$validator->validate())
{
    
//Do stuff with data
}
else 
{
    
//Handle error
    
$errors $validator->getErrors();
}


I embed the code above in my data objects in a method that persists the object on success, and throws an exception on validation errors so I can can simply do this in my controllers:
try
{
    
$contact = new Contact();
    
$contact->setName($request->getParameter('name'));
    
$contact->setEmail($request->getParameter('email'));
    
$contact->setComment($request->getParameter('comment'));
    
$contact->store();
}
catch (
ValidationException $e)
{
    
$errors $e->getErrors();
    
$status 'validation_error';
}


I then pass the status and the array of errors to a smarty template that handles the error display. The controller doesn't need to be aware of any business logic, it simply handles the flow of data between the UI and the business objects.