Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Easiest Form validation library for PHP? [closed]

I need a simple php library which can be used to easily pass rules and field names to, and then validation could be easily performed. There should also be an easy way to retrieve the errors.

Any suggestions?

like image 903
Ali Avatar asked Apr 10 '09 11:04

Ali


People also ask

Can PHP be used for validation?

PHP Form Validation code is a set of validation rules that allows you to create server-side validation to the PHP forms quickly with little efforts. Form validation is really crucial for dynamic web pages.


2 Answers

I wrote a simple class of my own, combining some regexes i collected over the years with PHP's sanatize and filter functions.

<? /**  * Pork Formvalidator. validates fields by regexes and can sanatize them. Uses PHP filter_var built-in functions and extra regexes   * @package pork  */   /**  * Pork.FormValidator  * Validates arrays or properties by setting up simple arrays  *   * @package pork  * @author SchizoDuckie  * @copyright SchizoDuckie 2009  * @version 1.0  * @access public  */ class FormValidator {     public static $regexes = Array(             'date' => "^[0-9]{4}[-/][0-9]{1,2}[-/][0-9]{1,2}\$",             'amount' => "^[-]?[0-9]+\$",             'number' => "^[-]?[0-9,]+\$",             'alfanum' => "^[0-9a-zA-Z ,.-_\\s\?\!]+\$",             'not_empty' => "[a-z0-9A-Z]+",             'words' => "^[A-Za-z]+[A-Za-z \\s]*\$",             'phone' => "^[0-9]{10,11}\$",             'zipcode' => "^[1-9][0-9]{3}[a-zA-Z]{2}\$",             'plate' => "^([0-9a-zA-Z]{2}[-]){2}[0-9a-zA-Z]{2}\$",             'price' => "^[0-9.,]*(([.,][-])|([.,][0-9]{2}))?\$",             '2digitopt' => "^\d+(\,\d{2})?\$",             '2digitforce' => "^\d+\,\d\d\$",             'anything' => "^[\d\D]{1,}\$"     );     private $validations, $sanatations, $mandatories, $errors, $corrects, $fields;       public function __construct($validations=array(), $mandatories = array(), $sanatations = array())     {         $this->validations = $validations;         $this->sanatations = $sanatations;         $this->mandatories = $mandatories;         $this->errors = array();         $this->corrects = array();     }      /**      * Validates an array of items (if needed) and returns true or false      *      */     public function validate($items)     {         $this->fields = $items;         $havefailures = false;         foreach($items as $key=>$val)         {             if((strlen($val) == 0 || array_search($key, $this->validations) === false) && array_search($key, $this->mandatories) === false)              {                 $this->corrects[] = $key;                 continue;             }             $result = self::validateItem($val, $this->validations[$key]);             if($result === false) {                 $havefailures = true;                 $this->addError($key, $this->validations[$key]);             }             else             {                 $this->corrects[] = $key;             }         }          return(!$havefailures);     }      /**      *      *  Adds unvalidated class to thos elements that are not validated. Removes them from classes that are.      */     public function getScript() {         if(!empty($this->errors))         {             $errors = array();             foreach($this->errors as $key=>$val) { $errors[] = "'INPUT[name={$key}]'"; }              $output = '$$('.implode(',', $errors).').addClass("unvalidated");';              $output .= "alert('there are errors in the form');"; // or your nice validation here         }         if(!empty($this->corrects))         {             $corrects = array();             foreach($this->corrects as $key) { $corrects[] = "'INPUT[name={$key}]'"; }             $output .= '$$('.implode(',', $corrects).').removeClass("unvalidated");';            }         $output = "<script type='text/javascript'>{$output} </script>";         return($output);     }       /**      *      * Sanatizes an array of items according to the $this->sanatations      * sanatations will be standard of type string, but can also be specified.      * For ease of use, this syntax is accepted:      * $sanatations = array('fieldname', 'otherfieldname'=>'float');      */     public function sanatize($items)     {         foreach($items as $key=>$val)         {             if(array_search($key, $this->sanatations) === false && !array_key_exists($key, $this->sanatations)) continue;             $items[$key] = self::sanatizeItem($val, $this->validations[$key]);         }         return($items);     }       /**      *      * Adds an error to the errors array.      */      private function addError($field, $type='string')     {         $this->errors[$field] = $type;     }      /**      *      * Sanatize a single var according to $type.      * Allows for static calling to allow simple sanatization      */     public static function sanatizeItem($var, $type)     {         $flags = NULL;         switch($type)         {             case 'url':                 $filter = FILTER_SANITIZE_URL;             break;             case 'int':                 $filter = FILTER_SANITIZE_NUMBER_INT;             break;             case 'float':                 $filter = FILTER_SANITIZE_NUMBER_FLOAT;                 $flags = FILTER_FLAG_ALLOW_FRACTION | FILTER_FLAG_ALLOW_THOUSAND;             break;             case 'email':                 $var = substr($var, 0, 254);                 $filter = FILTER_SANITIZE_EMAIL;             break;             case 'string':             default:                 $filter = FILTER_SANITIZE_STRING;                 $flags = FILTER_FLAG_NO_ENCODE_QUOTES;             break;          }         $output = filter_var($var, $filter, $flags);                 return($output);     }      /**       *      * Validates a single var according to $type.      * Allows for static calling to allow simple validation.      *      */     public static function validateItem($var, $type)     {         if(array_key_exists($type, self::$regexes))         {             $returnval =  filter_var($var, FILTER_VALIDATE_REGEXP, array("options"=> array("regexp"=>'!'.self::$regexes[$type].'!i'))) !== false;             return($returnval);         }         $filter = false;         switch($type)         {             case 'email':                 $var = substr($var, 0, 254);                 $filter = FILTER_VALIDATE_EMAIL;                 break;             case 'int':                 $filter = FILTER_VALIDATE_INT;             break;             case 'boolean':                 $filter = FILTER_VALIDATE_BOOLEAN;             break;             case 'ip':                 $filter = FILTER_VALIDATE_IP;             break;             case 'url':                 $filter = FILTER_VALIDATE_URL;             break;         }         return ($filter === false) ? false : filter_var($var, $filter) !== false ? true : false;     }           } 

Now this requires mootools for some of the javascript you see here, but you can easily change that to your favorite javascript framework. All it does is look up the element, and add the 'unvalidated' CSS class to it.

Usage is as simple as i always ever wanted:

Example:

$validations = array(     'name' => 'anything',     'email' => 'email',     'alias' => 'anything',     'pwd'=>'anything',     'gsm' => 'phone',     'birthdate' => 'date'); $required = array('name', 'email', 'alias', 'pwd'); $sanatize = array('alias');  $validator = new FormValidator($validations, $required, $sanatize);  if($validator->validate($_POST)) {     $_POST = $validator->sanatize($_POST);     // now do your saving, $_POST has been sanatized.     die($validator->getScript()."<script type='text/javascript'>alert('saved changes');</script>"); } else {     die($validator->getScript()); } 

To validate just one element:

$validated = new FormValidator()->validate('blah@bla.', 'email'); 

To sanatize just one element:

$sanatized = new FormValidator()->sanatize('<b>blah</b>', 'string'); 

The coolest thing about this class is that you can send your form with an ajax or iframe target and execute the resulting script. No need to refresh the page or re-send the same form data back to the browser :) Also, if the script needs changing, there's no difficult overdesigned framework to analyze, just change it any way you want :)

Oh yeah, feel free to use this anywhere you want. No licenses

like image 61
SchizoDuckie Avatar answered Sep 17 '22 16:09

SchizoDuckie


The answer from SchizoDuckie above was awesome. I've used his code in project I'm working on with the permission of the author. One issue I had using this code was that if a required field was not submitted then it would not register an error. I've modified the code to cover this scenario. I've also removed the code to generate HTML and javascript as my project demands separation of UI from logic per MVC pattern. The modified code simply returns JSON encoded result. I repost the modified code here in case it is of some use to others.

<? /** * Pork Formvalidator. validates fields by regexes and can sanatize them. Uses PHP       filter_var built-in functions and extra regexes  * @package pork */   /** * Pork.FormValidator * Validates arrays or properties by setting up simple arrays *  * @package pork * @author SchizoDuckie * @copyright SchizoDuckie 2009 * @version 1.0 * @access public */ class FormValidator {     public static $regexes = Array(             'date' => "^[0-9]{4}[-/][0-9]{1,2}[-/][0-9]{1,2}\$",             'amount' => "^[-]?[0-9]+\$",             'number' => "^[-]?[0-9,]+\$",             'alfanum' => "^[0-9a-zA-Z ,.-_\\s\?\!]+\$",             'not_empty' => "[a-z0-9A-Z]+",             'words' => "^[A-Za-z]+[A-Za-z \\s]*\$",             'phone' => "^[0-9]{10,11}\$",             'zipcode' => "^[1-9][0-9]{3}[a-zA-Z]{2}\$",             'plate' => "^([0-9a-zA-Z]{2}[-]){2}[0-9a-zA-Z]{2}\$",             'price' => "^[0-9.,]*(([.,][-])|([.,][0-9]{2}))?\$",             '2digitopt' => "^\d+(\,\d{2})?\$",             '2digitforce' => "^\d+\,\d\d\$",             'anything' => "^[\d\D]{1,}\$",             'username' => "^[\w]{3,32}\$" );  private $validations, $sanatations, $mandatories, $equal, $errors, $corrects, $fields;   public function __construct($validations=array(), $mandatories = array(), $sanatations = array(), $equal=array()) {     $this->validations = $validations;     $this->sanatations = $sanatations;     $this->mandatories = $mandatories;     $this->equal = $equal;     $this->errors = array();     $this->corrects = array(); }  /**  * Validates an array of items (if needed) and returns true or false  *  * JP modofied this function so that it checks fields even if they are not submitted.  * for example the original code did not check for a mandatory field if it was not submitted.  * Also the types of non mandatory fields were not checked.  */ public function validate($items) {     $this->fields = $items;     $havefailures = false;      //Check for mandatories     foreach($this->mandatories as $key=>$val)     {         if(!array_key_exists($val,$items))         {             $havefailures = true;             $this->addError($val);         }     }      //Check for equal fields     foreach($this->equal as $key=>$val)     {         //check that the equals field exists         if(!array_key_exists($key,$items))         {             $havefailures = true;             $this->addError($val);         }          //check that the field it's supposed to equal exists         if(!array_key_exists($val,$items))         {             $havefailures = true;             $this->addError($val);         }          //Check that the two fields are equal         if($items[$key] != $items[$val])         {             $havefailures = true;             $this->addError($key);         }     }      foreach($this->validations as $key=>$val)     {             //An empty value or one that is not in the list of validations or one that is not in our list of mandatories             if(!array_key_exists($key,$items))              {                     $this->addError($key, $val);                     continue;             }              $result = self::validateItem($items[$key], $val);              if($result === false) {                     $havefailures = true;                     $this->addError($key, $val);             }             else             {                     $this->corrects[] = $key;             }     }      return(!$havefailures); }  /* JP  * Returns a JSON encoded array containing the names of fields with errors and those without.  */ public function getJSON() {      $errors = array();      $correct = array();      if(!empty($this->errors))     {                     foreach($this->errors as $key=>$val) { $errors[$key] = $val; }                 }      if(!empty($this->corrects))     {         foreach($this->corrects as $key=>$val) { $correct[$key] = $val; }                     }      $output = array('errors' => $errors, 'correct' => $correct);      return json_encode($output); }    /**  *  * Sanatizes an array of items according to the $this->sanatations  * sanatations will be standard of type string, but can also be specified.  * For ease of use, this syntax is accepted:  * $sanatations = array('fieldname', 'otherfieldname'=>'float');  */ public function sanatize($items) {     foreach($items as $key=>$val)     {             if(array_search($key, $this->sanatations) === false && !array_key_exists($key, $this->sanatations)) continue;             $items[$key] = self::sanatizeItem($val, $this->validations[$key]);     }     return($items); }   /**  *  * Adds an error to the errors array.  */  private function addError($field, $type='string') {     $this->errors[$field] = $type; }  /**  *  * Sanatize a single var according to $type.  * Allows for static calling to allow simple sanatization  */ public static function sanatizeItem($var, $type) {     $flags = NULL;     switch($type)     {             case 'url':                     $filter = FILTER_SANITIZE_URL;             break;             case 'int':                     $filter = FILTER_SANITIZE_NUMBER_INT;             break;             case 'float':                     $filter = FILTER_SANITIZE_NUMBER_FLOAT;                     $flags = FILTER_FLAG_ALLOW_FRACTION | FILTER_FLAG_ALLOW_THOUSAND;             break;             case 'email':                     $var = substr($var, 0, 254);                     $filter = FILTER_SANITIZE_EMAIL;             break;             case 'string':             default:                     $filter = FILTER_SANITIZE_STRING;                     $flags = FILTER_FLAG_NO_ENCODE_QUOTES;             break;      }     $output = filter_var($var, $filter, $flags);                 return($output); }  /**   *  * Validates a single var according to $type.  * Allows for static calling to allow simple validation.  *  */ public static function validateItem($var, $type) {     if(array_key_exists($type, self::$regexes))     {             $returnval =  filter_var($var, FILTER_VALIDATE_REGEXP, array("options"=> array("regexp"=>'!'.self::$regexes[$type].'!i'))) !== false;             return($returnval);     }     $filter = false;     switch($type)     {             case 'email':                     $var = substr($var, 0, 254);                     $filter = FILTER_VALIDATE_EMAIL;                     break;             case 'int':                     $filter = FILTER_VALIDATE_INT;             break;             case 'boolean':                     $filter = FILTER_VALIDATE_BOOLEAN;             break;             case 'ip':                     $filter = FILTER_VALIDATE_IP;             break;             case 'url':                     $filter = FILTER_VALIDATE_URL;             break;     }     return ($filter === false) ? false : filter_var($var, $filter) !== false ? true :     false; }            } ?> 
like image 38
John Pendlebury Avatar answered Sep 18 '22 16:09

John Pendlebury