Validating user input with functions in PHP
Created:09 Sep 2017 21:07:45 , in Web development
User input validation is one of the oldest and most frequently occurring problems in computer programming. It crops up regardless of programming language and at almost every project.
If not dealt with skillfully, in particular when larger amount of user input is involved, it can quickly turn any project into a difficult to complete and susceptible to hacks nightmare.
Technically, the problem is not the most demanding one, though.
When I think of input validation at the high level, a simple mapping from one boolean data type value to itself or to the other comes to my mind.
To put this in simple terms, at the beginning I make an assumption, perhaps too optimistically, that all the input is correct. Though, in the second step, I start looking at every bit of the data more and more closely. This is the part when tools like functions prove indispensable. All of them return either true or false. My initial assumption about the input remains unchanged unless one of the validating functions returns boolean false. If none of them returns the value, my program moves on to the next stage, perhaps one that involves the input manipulation. Otherwise, some input parts have to be corrected before the next stage can be reached.
Now, how this high level, somewhat abstract thinking of input validation can be turned into flexible and easy to use code?My approach is described best by a tiny PHP class called SWWWValidation.
The class validates input ( passed as an associative array of values), with help of rules. Each such rule checks for just one particular property of input data, like whether required part of it exists, is an array, or perhaps is a number in range from 0 to 100. The rules rely upon functions for checks entirely. Once all the rules have been run, validation result is known. Input is either valid or not. Validation errors are set in the same time.
Validation class
Here is SWWWValidation class listing:
/*
Class: SWWWValidation
Description: Validate user input
Author: Sylwester Wojnowski
WWW: wojnowski.net.pl
Methods:
instnce($input) - public static - get instance of SWWWValidation
parameters:
$input - array - associative array of key/value pairs
return - object - instance of SWWWValidation
rule($key,$func,$args,$error) - public - set validation rule
parameters:
$key - string - index in $input array
$func - function - callback
[$args] - array - arguments to be passed to $func
[$error] - string - error message
return - string - feedback for the score
ckeck() - public - check input for validity
return - bool
errors($key) - public - recover errors
parameters:
[$key] - string - index in $input array
return - array - array of arrays of error strings
error($key,$error) - public - set error
parameters:
$key - string index in $input array
$error - string
return - object - validation
*/
class SWWWValidation{
const INVALID_INPUT = "Input should be given as array of key/value pairs.";
private $rules = array();
private $errors = array();
private $input = null;
// get instance
public static function instance($input = array()){
return new SWWWValidation($input);
}
public function __construct($input){
if(!is_array($input)){ throw new Exception(self::INVALID_INPUT); }
$this -> input = $input;
}
// add rule
public function rule($key,$func,$args = array(':value'),$error = ''){
$params = array();
if(!array_key_exists($key,$this -> rules)){ $this -> rules[$key] = array(); }
$func = is_array($func) && count($func) === 1 ? $func[0] : $func;
// replace :value,:validation,:data
foreach($args as $arg){
switch($arg){
case ':value':
$params[] = $this -> input[$key];
break;
case ':validation':
$params[] = $this;
break;
case ':input':
$params[] = $this -> input;
break;
default:
$params[] = $arg;
}
}
$this -> rules[$key][] = array($func,$params,$error);
return $this;
}
// validate input
public function check(){
foreach($this -> rules as $key => $ruleset){
foreach($ruleset as $rule){
$result = null;
$result = call_user_func_array($rule[0],$rule[1]);
if(!$result){
// set error
$this -> error($key,$rule[2]);
}
}
}
return empty($this -> errors);
}
// return error messages
public function errors($key = ''){
if(!empty($key)){
return $this -> errors[$key];
}
// return all errors
return $this -> errors;
}
// set error message
public function error($key,$error){
if(!array_key_exists($key,$this -> errors)){
$this -> errors[$key] = array();
}
$this -> errors[$key][] = $error;
return $this;
}
}
Configuration
As mentioned above, SWWWValidation (or more accurately its instance method) accepts an associative array of values to be checked for validity. Not much more there is to say in this place. We shall move on to an use example next.
Use example
Let's assume that, an array of input data like the one below is to be validated using SWWWValidation:
$input = array(
'firstname' => null,
'surename' => 'Trewin',
'age' => 22,
'email' => 'email@domain.ext',
'repeat_email' => 'email@domain.ext'
);
Some functions, will be needed to validate the above. The three given below are anonymous ones. Each of them returns the boolean data type (either true or false).
// check for value existence
$exists = function($value){
return isset($value);
};
// check whether value is an empty string or not
$not_empty = function($value){
return !empty((string)$value);
};
// check whether value matches $input['repeat_email'] - a specific one
$matches = function($value,$input){
return $value === $input['repeat_email'];
};
SWWWValidation can accept not just anonymous functions but any type of function available in PHP programming language like built-in functions, object methods or static class methods.
Here a callback given as a static class method.
class SWWWValidationCallbacks{
// invalid email error message
const INVALID_EMAIL = 'Email is invalid';
// valid email
public static function email($value){
return (bool)preg_match('/^[A-Z0-9._-]+@[A-Z0-9.-]+\.[A-Z0-9.-]+$/i',$value);
}
}
The class contains an error message which can be passed together with the function to a rule.
Moving on to the nitty-gritty of validating input with SWWWValidation:
Obtain validation object:
$v = SWWWValidation::instance($input);
Add rules to fields you need validated:
// use callback function
$v -> rule('surename',$not_empty,array(':value'));
// use built-in in_array function
$v -> rule('age','in_array',array(':value',range(0,100)));
// check whether email matches repeat_email with anonymous function
$v -> rule('email',$matches,array(':value',':input'));
// use static class method as a callback
$v -> rule(
'email',
array('SWWWValidationCallbacks','email'),
array(':value'),
SWWWValidationCallbacks::INVALID_EMAIL
);
Check, whether the input is valid:
$v -> check();
=> true
Let's add some rule that makes the input invalid and check again:
$v -> rule('firstname', $exists, array(':value'),'First name not given!');
$v -> check();
=> false
Now, incidentally, the last rule has the fourth parameter specified. It is an error message which, if the rule did not pass, would be recovered in the manner shown below.
Obtaining errors
All the errors can be obtained by calling errors method:
$v -> errors();
=> array(
'firstname' => array('First name not given!')
)
Errors for a particular key of input array can be recovered by passing the key to the method:
$v -> errors('firstname')
=> array('First name not given!')
Each piece of input data can have as many rules check it as necessary. Each of these rules can have an error message passed to it.
A word about rules
Rule is just a validation object method, it can accept up to 4 parameters.
First of them is a key in input array value at which in the array to be validated.
The second is a function to be used to validated the value.
The third parameter is an array of values to be passed to the callback function.
Apart from standard parameters, this array can contain strings like:
:value - gets replaced with value at the given key in input array before being passed to callback function
:validation - gets replaced with validation object before being passed to callback function.
:input - gets replaced with input array before being passed to callback function.
The fourth, optional parameter, is already mentioned error string.
And that's all there is to SWWWValidation.
Final thoughts
As I mentioned above,at the high level input validation can be thought of as a mapping from either one boolean value to itself or to the other. Functions are a crucial linchpin in the process. SWWWValidation is just my implementation of this basic idea in PHP.
I hope you enjoyed the article, found it instructive and the code easy to get.
This post was updated on 09 Sep 2017 21:10:20
Tags: php
Author, Copyright and citation
Author
Author of the this article - Sylwester Wojnowski - is a sWWW web developer. He has been writing computer code for the websites and web applications since 1998.
Copyrights
©Copyright, 2024 Sylwester Wojnowski. This article may not be reproduced or published as a whole or in parts without permission from the author. If you share it, please give author credit and do not remove embedded links.
Computer code, if present in the article, is excluded from the above and licensed under GPLv3.
Citation
Cite this article as:
Wojnowski, Sylwester. "Validating user input with functions in PHP." From sWWW - Code For The Web . https://swww.com.pl//main/index/validating-user-input-with-functions-in-php
Add Comment