Right now, I'm doing error handling within the form validation class. This feels very ugly to me because "objects are supposed to do one thing, and do it well". Well, if it's validating, why should it be handling errors? Unfortunately I don't know of any other way to do it.
So here's my form validator base class
Code: Select all
<?php
/**
* This is a form validator class to validate forms.
*
* @author Scott Martin <smp_info[at]yahoo[dot]com>
*/
//load in our rules
require_once 'class/formvalidator/rule/length.php';
require_once 'class/formvalidator/rule/required.php';
require_once 'class/formvalidator/rule/regex.php';
require_once 'class/formvalidator/rule/match.php';
class formValidator
{
//container for rules
protected $_rules = array();
//container for potential errors
protected $_potentialErrors = array();
//container for errors
protected $_errors = array();
/**
* Method to add rules
*/
public function addRule(formValidator $rule, $errorMessage)
{
$this->_rules = array_merge_recursive($this->_rules, $rule->_add());
$this->_potentialErrors = array_merge_recursive($this->_potentialErrors, $rule->_setError($errorMessage));
}
public function getErrors()
{
return $this->_errors;
}
//runs through different validating methods
public function validate()
{
$this->_validateRequired();
$this->_validateLength();
$this->_validateRegex();
$this->_validateMatch();
return empty($this->_errors);
}
//checks required fields are filled in
private function _validateRequired()
{
if (!empty($this->_rules['required']))
{
foreach ($this->_rules['required'] AS $required)
{
if (empty($_POST[$required]) || (trim($_POST[$required]) == ''))
{
$this->_errors[] = $this->_potentialErrors['required'];
return;
}
}
}
}
//checks that fields have the appropriate lengths
private function _validateLength()
{
if (!empty($this->_rules['length']))
{
$it = 0;
foreach ($this->_rules['length'] AS $field => $length)
{
$strlen = strlen($_POST[$field]);
if (($strlen < $length['minLength']))
{
$this->_errors[] = is_array($this->_potentialErrors['length']) ?
$this->_potentialErrors['length'][$it] : $this->_potentialErrors['length'];
}
if ($length['maxLength'] && ($strlen > $length['maxLength']))
{
$this->_errors[] = is_array($this->_potentialErrors['length']) ?
$this->_potentialErrors['length'][$it] : $this->_potentialErrors['length'];
}
$it++;
}
}
}
//checks that fields have the appropriate characters
private function _validateRegex()
{
//regex rules
if (!empty($this->_rules['regex']))
{
$it = 0;
foreach ($this->_rules['regex'] AS $field => $pattern)
{
if (!preg_match($pattern, $_POST[$field]))
{
$this->_errors[] = is_array($this->_potentialErrors['regex']) ?
$this->_potentialErrors['regex'][$it] : $this->_potentialErrors['regex'];
}
$it++;
}
}
}
//checks that field1 matches field2 in value
private function _validateMatch()
{
//match rules
if (!empty($this->_rules['match']))
{
$it = 0;
foreach ($this->_rules['match'] AS $match)
{
if ($_POST[$match[0]] != $_POST[$match[1]])
{
$this->_errors[] = is_array($this->_potentialErrors['match']) ?
$this->_potentialErrors['match'][$it] : $this->_potentialErrors['match'];
}
$it++;
}
}
}
}Code: Select all
<?php
class formValidator_Rule_Required extends formValidator
{
private $_field;
public function __construct($field)
{
$this->_field = $field;
}
protected function _add()
{
$ret = array();
if (is_array($this->_field))
{
foreach ($this->_field AS $field)
{
$ret['required'][] = $field;
}
} else
{
$ret['required'] = $this->_field;
}
return $ret;
}
protected function _setError($errorMessage)
{
return array('required' => $errorMessage);
}
}Code: Select all
<?php
class formValidator_Rule_Length extends formValidator
{
private $_field;
private $_minLength;
private $_maxLength;
public function __construct($field, $minLength=false, $maxLength=false)
{
$this->_field = $field;
$this->_minLength = $minLength;
$this->_maxLength = $maxLength;
}
protected function _add()
{
$ret = array();
$ret['length'] = array(
$this->_field => array(
'minLength' => $this->_minLength,
'maxLength' => $this->_maxLength
)
);
return $ret;
}
protected function _setError($errorMessage)
{
return array('length' => $errorMessage);
}
}Code: Select all
<?php
class formValidator_Rule_Regex extends formValidator
{
private $_field;
private $_regex;
public function __construct($field, $regex)
{
$this->_field = $field;
$this->_regex = $regex;
}
protected function _add()
{
$ret = array();
$ret['regex'] = array($this->_field => $this->_regex);
return $ret;
}
protected function _setError($errorMessage)
{
return array('regex' => $errorMessage);
}
}Code: Select all
<?php
class formValidator_Rule_Match extends formValidator
{
private $_field1;
private $_field2;
public function __construct($field1, $field2)
{
$this->_field1 = $field1;
$this->_field2 = $field2;
}
protected function _add()
{
$ret = array();
$ret['match'][] = array($this->_field1, $this->_field2);
return $ret;
}
protected function _setError($errorMessage)
{
return array('match' => $errorMessage);
}
}Code: Select all
<?php
//page title
$title = 'Sign up for a free account';
//page header
require 'header.php';
//control variable for whether or not to show the form
$showForm = true;
//was form posted?
if (!empty($_POST['action']) && ($_POST['action'] == 'register'))
{
//form validation object
require_once 'class/formvalidator/formvalidator.php';
$fv = new formValidator();
//add rules
$fv->addRule(
new formValidator_Rule_Required(array('username', 'password', 'passwordConfirm', 'email', 'emailConfirm')),
'Please fill in all of the required fields.'
);
$fv->addRule(
new formValidator_Rule_Length('username', 3, 25),
'Your username must be between 3 and 25 characters in length.'
);
$fv->addRule(
new formValidator_Rule_Length('password', 6, false),
'Your password must be at least 6 characters in length.'
);
$fv->addRule(
new formValidator_Rule_Regex('username', '/[\w]+/'),
'Your username may only contain the characters a-z, 0-9, and underscores.'
);
$fv->addRule(
new formValidator_Rule_Match('password', 'passwordConfirm'),
'Your passwords do not match.'
);
$fv->addRule(
new formValidator_Rule_Match('email', 'emailConfirm'),
'Your email addresses do not match.'
);
if ($fv->validate())
{
echo 'validates';
//do this
$showForm = false;
} else
{
//the form did not validate
//assign the errors to the template
$tpl->assign('errors', $fv->getErrors());
//show the form again with posted values
$tpl->assign('username', !empty($_POST['username']) ? htmlentities($_POST['username'], ENT_QUOTES) : '');
$tpl->assign('email', !empty($_POST['email']) ? htmlentities($_POST['email'], ENT_QUOTES) : '');
$tpl->assign('emailConfirm', !empty($_POST['emailConfirm']) ? htmlentities($_POST['emailConfirm'], ENT_QUOTES) : '');
}
}
//assign the showForm control variable
$tpl->assign('showForm', $showForm);
//display the page
$tpl->display('register.tpl');
//page footer
require 'footer.php';Thanks a lot!