PHP Programming/OOP5/Advanced Input Validation
<?php
/* created by nemesiskoen */

$pv = new InputValidator($_POST);

if($pv->exists('submit')) { // is the value 'submit' set in the $_POST array?

    $pv->hasValue('age', 'You must enter an age');
    $pv->hasValue('email', 'You must enter an email');
    // ...

    $pv->isInt('age', 'You must enter a valid age.');
    $pv->isEmail('email', 'You must enter a valid email.');
    $pv->hasMinLength('username', 2, "You're username needs to be at least 2 characters long.");
    $pv->matchbool(someFunction, 'The function returned false!');
    $pv->matchRegex('username', REGEX_HERE, 'error message here');
    $pv->equals('password1', $pv->get('password2'), "Passwords don't match.");
    $pv->equals('password1', $pv->get('username'), "Password can't be the same as your username.");
    $pv->isUrl('website', 'You must enter a valid website.');

    if($pv->render) {
        // form successfully submitted!
    }

}

$pv->assignToTemplate($tpl); // if you work with a template parser this will assign ALL values again, with the same name, but prefixed by 'p'.

// otherwise you can query the error array as followed:
$errors = $pv->getErrors;
// loop through the errors
echo 'The form couldn\'t submt because: <br />';
foreach($errors as $v) {
    echo $v . '<br />';
}

?>

<?php

/**
 * @package DP_InputValidator
 *
 */

class DP_InputValidator_Abstract {
	
	/**
	 * Mainarray
	 *
	 * @access protected
	 * @var array $_array
	 */
	
	protected $_array = array;
	
	/**
	 * All errorstring
	 *
	 * @access protected
	 * @var array $_errorStrings
	 */
	
	protected $_errorStrings = array;
	
	/**
	 * Errorstrings
	 *
	 * @access public
	 * @var string $noValueError
	 * @var string $noIntError
	 * @var string $noEmailError
	 * @var string $noRegexError
	 * @var string $equalError
	 * @var string $noEqualError
	 * @var string $noMinLengthError
	 */
	
	public $noValueError = "%s has no value";
	public $noIntError = "%s is no int";
	public $noEmailError = "%s is not a valid email";
	public $noRegexError = "%s doesn't match a certain regex";
	public $equalError = "%s equals something that isn't allowed!";
	public $noEqualError = "%s doesn't equal something, which is required!";
	public $noMinLengthError = "%s must be a certain length!";
	public $noIssetError = "%s is not set!";
	
	/**
	 * Set the array to validate
	 *
	 * @access protected
	 * @param array &$array
	 * @param bool $safe
	 */	
	protected function __construct(&$array, $safe = true) {
		$this->_array = $array;
		if($safe) {
			$array = null;
		}
	}
	
	/**
	 * Get a secured item of the array
	 *
	 * @access public
	 * @param string $key
	 * @return mixed
	 */
	public function get($key) {
		return $this->_secureArray($this->_array[$key]);
	}

	/**
	 * Get a raw item of the array
	 *
	 * @access public
	 * @param string $key
	 * @return string
	 */   
	public function value($key) {
		return $this->_array[$key];
	}
 
	/**
	 * Get the whole array, if secured is set to true then the array will be secured
	 * 
	 * @access public
	 * @param bool $secure = true
	 * @param mixed $noSubmit = 'submit'
	 * @return array
	 */
	public function getArray($secure = true, $noSubmit = 'submit') {
		$array = $this->_array;
		if($secure) {
			foreach($array as $k => $v) {
				if(is_array($v)) {
					$array[$k] = $this->_secureArray($v);
				} else {
					$array[$k] = htmlsecure($v);
				}
			}
		}
		
		if($noSubmit) {
			unset($array[$noSubmit]);
		}
		
		return (array) $array;		
	}
	
	/**
	 * Render method 
	 * if a fault has a occurred, an no exception is thrown: 
	 * this function will throw an exception (depending of the $throw parameter)
	 * If the $reset parameter is set to true, all the errorArrays will be reset
	 * throws Exception
	 *
	 * @access public
	 * @param bool $reset
	 * @return bool
	 */
	public function render($reset = true) {
		$checks = $this->_getAllErrorArrays;
		$aantal = 0;
		foreach($checks as $v) {
			$var = '_' . $v;
			$count += count($this->$var);
			if($reset) $this->$var = array;
		}
		$return = ($count == 0 && count($this->_errorStrings) == 0);
		if($reset && $return) $this->_errorStrings = array;
		return $return;
	}
	
	/**
	 * Set a var, override if $override is set on true
	 *
	 * @param string $var
	 * @param string $value
	 * @param bool $overwrite
	 */
	public function setVar($var, $value = "", $overwrite = true) {		
		if(is_array($var)) {
			foreach($var as $k => $v) {
				$this->setVar($k, $v, $value);
			}
		} elseif(!isset($this->_array[$var]) || $overwrite) {
			$this->_array[$var] = $value;
		}
	}
	
	/**
	 * Unset a var
	 *
	 * @param string $varName
	 */
	public function unsetVar($varName) {
		if($this->exists($varName)) {
			unset($this->_array[$varName]);
		}
	}
	
	/**
	 * Get all the occurred errorStrings, if the $multiD parameter is set to true
	 * the return array will be multiDimensional
	 * otherwise it will be a 1D array
	 *
	 * @access public
	 * @param bool $multiD = false
	 * @return array
	 */ 
	public function getErrorStrings($multiD = false) {
		if($multiD) {
			return $this->_errorStrings;
		}
		
		$return = array;
		foreach($this->_errorStrings as $array) {
			foreach($array as $value) {
				$return[] = $value;
			}
		}
		
		return (array) $return;
	}
	
	
	/**
	 * Assign the errors to a templatePower template.
	 *
	 * @access public
	 * @param string $tpl
	 * @param string $block
	 * @param string $var
	 * @return InputValidator_Abstract
	 */
	public function assignToTemplate($tpl) {
		$tpl->assign($this->getArray, true, false, 'p_');
		$errorstrings = $this->getErrorStrings;
		
		$tpl->assign('error', count($errorstrings) > 0);
		$tpl->assign('errors', $errorstrings);
		
		return $this;
	}
	
	/**
	 * If one of the 'check'-methods is given an array as argument, this method will handle this
	 *
	 * @access protected
	 * @param bool $multiD
	 * @return array
	 */ 
	protected function _handleArray($keys, $function, $errorString) {
		$ok = true;
		foreach($keys as $v) {
			if(!$this->$function($v, $errorString)) $ok = false;
		}
		return $ok;
	}
	
	/**
	 * Secure a multi-dimensional array or a string
	 *
	 * @access protected
	 * @param mixed $array
	 * @return mixed
	 */ 
	protected function _secureArray($input) {
		$return = '';
		if(is_array($input)) {
			$return = array;
			foreach($input as $k => $v) {
				if(is_array($v)) {
					$return[$k] = $this->_secureArray($v);
				} else {
					$return[$k] = htmlentities($v);
				}
			}
		} else {
			$return = htmlentities($input);
		}
		return $return;
	}
	
	/**
	 * Add an error string
	 * if alternative is given, it will be used in the 'sprintf' statement
	 *
	 * @access protected
	 * @param string $key
	 * @param string $string
	 * @param string $alternative = ""
	 * @return bool (false)
	 */
	  protected function _addErrorString($key, $string) {
		if(!isset($this->_errorStrings[$key])) {
			$this->_errorStrings[$key] = array;
		}
		$this->_errorStrings[$key][] = $string;
		return false;
	}
	
	/**
	 * This function will return all the error Arrays that are used by the 'check'-methods
	 *
	 * @access protected
	 * @param void
	 * @return array
	 */
	protected function _getAllErrorArrays {
		return array('noValue', 'noInt', 'noEmail', 'noRegex', 'equals', 'noEquals', 'noMinLength');
	}
	
	
	/**
	 * Process an error
	 *
	 * @access protected
	 * @param string $type
	 * @param string $key
	 * @param string $errorString
	 * @return InputValidator_Abstract
	 */
	protected function _processError($type, $key, $errorString) {
		if(isset($this->$type) && is_array($this->$type)) {
			array_push($this->$type, $key);
			$this->_addErrorString($key, $errorString);
		}
		return $this;
	}
	
	/**
	 * Is called by __call when the user wants to withdraw an error
	 *
	 * @access protected
	 * @param string $method
	 * @param array $arg
	 * @return string
	 */
	protected function _handleFetchError($method, $arg) {
		list($key, $name, $string) = $arg;
		$errorstring = $method . "Error";
		$n = $name != null ? $name : $key;
		$errstr = $string != null ? $string : $this->$errorstring;
		return in_array($key, $this->$var) ? sprintf($errstr, $n) : "";
	}
	
	/**
	 * Is called by __call to validate a field.
	 *
	 * @access protected
	 * @param string $method
	 * @param array $arg
	 * @return mixed
	 */
	protected function _handleValidate($method, $arg) {
		$key = $arg[0];
		if(is_array($key) && (count($key) == 1 || count($key) == 2)) {
			return $this->_handleArray($key, $method, $arg[1]);
		} else {
			if(is_bool($key)) {
				if(!in_array($method, $this->_boolFunctions)) 
					return false;
			} elseif(!$this->exists($key) && $method != "_Validate_isset") {
				return false;
			}
			if(!call_user_func_array(array($this, $method), $arg)) {
				return $this->_addErrorString($key, end($arg));
			}
		}
		return true;
	}
	
	/**
	 * The __call method is used to process to situations:
	 * - if you want to check for errors
	 * - if you want to withdraw the errors
	 * 
	 * @access protected
	 * @param string $method
	 * @param array $arg
	 * @return mixed
	 */
	protected function __call($method, $arg) {
		
		$validateMethod = '_Validate_' . $method;
		/*
		 if the method exists "_Validate_' . $method" try to call it with 2 or 3 arguments
		 the rest will be handled as a public method itself, and not via __call
		*/
		if(method_exists($this, $validateMethod)) {
			return $this->_handleValidate($validateMethod, $arg);
		}
		/*
		 Otherwise lets see if the requested array is set, if the call is for example:
		 _noInt('age', 'leeftijd', '%s moet een getal zijn')
		*/
		$var = '_' . $method;
		if(isset($this->$var) && is_array($this->$var) && $this->$var != $this->_array) {
			return $this->_handleFetchError($method, $arg);
		}
		return null;
	}

}

?>

Add new methods to this class to validate.

<?php

/**
 * @package DP_InputValidator
 *
 */

class DP_InputValidator extends DP_InputValidator_Abstract {
	
	/**
	 * All error arrays
	 *
	 * @access protected
	 * @var array $_noValue
	 * @var array $_noInt
	 * @var array $_noEmail
	 * @var array $_noRegex
	 * @var array $_equals
	 * @var array $_noEquals
	 * @var array $_noMinLength
	 */
	
	protected $_noValue = array;
	protected $_noInt = array;
	protected $_noEmail = array;
	protected $_noRegex = array;
	protected $_equals = array;
	protected $_noEquals = array;
	protected $_noMinLength = array;
	protected $_noIsset = array;
	
	/**
	 * An array of all the functions that accept a boolean instead of a key.
	 * 
	 * @access protected
	 * @var array $_boolFunctions
	 */
	
	protected $_boolFunctions = array('_Validate_matchBool');
	
	/**
	 * Pass through to the Parent Constructor
	 *
	 * @param array &$array
	 * @param bool $safe
	 */	
	
	public function __construct(&$array, $safe = true) {
		parent::__construct($array, $safe);
	}
 
	/**
	 * Does an array key exist
	 *
	 * @param string $key
	 * @return bool
	 */ 
	public function exists($key) {
		if(is_string($key) || is_int($key)) {
			return array_key_exists($key, $this->_array);
		}
		return true;
	}
	
	/**
	 * Does it have a value?
	 *
	 * @access protected
	 * @param string $key
	 * @return bool
	 */ 
	public function _Validate_hasValue($key) {
		return ($this->_array[$key] != "");
	}
	
	/**
	 * Is it an integer?
	 *
	 * @access protected
	 * @param string $key
	 * @return bool
	 */ 
	public function _Validate_isInt($key) {
		return (strval(intval($this->_array[$key])) == $this->_array[$key]);
	}
	
	/**
	 * Is it a valid email?
	 *
	 * @access protected
	 * @param string $key
	 * @return bool
	 */ 
	public function _Validate_isEmail($key) {	  
		if(!validateEmailFormat($this->_array[$key])) { // ADD YOUR OWN EMAIL VALIDATION FUNCTION HERE
			return ($this->_array[$key] == '');
		}
		
		return true;
	}
	
	/**
	 * Is it a valid url?
	 *
	 * @access protected
	 * @param string $key
	 * @return bool
	 */
	public function _Validate_isUrl($key) {
		if(!validateUrlFormat($this->_array[$key])) {
			return ($this->_array[$key] == '');
		}
		
		return true;
	}
	
	/**
	 * Is it set?
	 * 
	 * @access protected
	 * @param string $key
	 * @return  bool
	 */
	public function _Validate_isset($key) {
		return isset($this->_array[$key]); 
	}
	
	/**
	 * Does it match a given regex?
	 * 
	 * @access protected
	 * @param mixed $key
	 * @param string $match
	 * @return bool
	 */ 
	public function _Validate_matchRegex($key, $match) {
		
		return (preg_match($match, $this->_array[$key]));
		
	}
	
	/**
	 * Does it equals '$value'?
	 * 
	 * @access public
	 * @param mixed $key
	 * @param string $value
	 * @param bool $case
	 * @return bool
	 */	 
	public function _Validate_equals($key, $value, $case) {		   
		if($case == false) {
			return (strtolower($this->_array[$key]) === strtolower($value));
		}
		return ($this->_array[$key] === $value);
			
	}
	
	/**
	 * Does the length differs from '$value'?
	 * 
	 * @access public
	 * @param mixed $key
	 * @param string $value
	 * @return bool
	 */	 
	public function _Validate_noEquals($key, $value) {
		
		return ($this->_array[$key] === $value);
	}
	
	/**
	 * Is the length longer than $length?
	 * 
	 * @access public
	 * @param mixed $key
	 * @param string $value
	 * @return bool
	 */
	public function _Validate_hasMinLength($key, $length) {
		
		return (strlen(trim($this->_array[$key])) >= $length);
		
	}	
	
	/**
	 * Is a bool true or false
	 * USE:
	 * $pv->matchBool(memberCheck($pv->get('member')), 'The member is already registered')
	 * 
	 * @access public
	 * @param mixed $key
	 * @return bool
	 */ 
	public function _Validate_matchBool($bool) {
		return $bool ? true : false;
	}

}

?>

  This article uses material from the Wikipedia page available here. It is released under the Creative Commons Attribution-Share-Alike License 3.0.

PHP_Programming/OOP5/Advanced_Input_validation
 



 

Connect with defaultLogic
What We've Done
Led Digital Marketing Efforts of Top 500 e-Retailers.
Worked with Top Brands at Leading Agencies.
Successfully Managed Over $50 million in Digital Ad Spend.
Developed Strategies and Processes that Enabled Brands to Grow During an Economic Downturn.
Taught Advanced Internet Marketing Strategies at the graduate level.


Manage research, learning and skills at defaultlogic.com. Create an account using LinkedIn to manage and organize your omni-channel knowledge. defaultlogic.com is like a shopping cart for information -- helping you to save, discuss and share.


  Contact Us