Bibliothèque de validation de Formulaire la plus simple pour PHP? [fermé]

J'ai besoin d'une bibliothèque php simple qui peut être utilisée pour passer facilement des règles et des noms de champs, puis la validation pourrait être facilement effectuée. Il devrait également y avoir un moyen facile de récupérer les erreurs.

Des suggestions?

31
demandé sur Click Upvote 2009-04-10 15:39:47

8 réponses

J'ai écrit une classe simple, combinant certaines expressions rationnelles que j'ai collectées au fil des ans avec les fonctions SANATIZE et filter de PHP.

<?
/**
 * 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;
    }       



}

Maintenant, cela nécessite mootools pour certains javascript que vous voyez ici, mais vous pouvez facilement changer cela à votre framework JavaScript préféré. Tout ce qu'il fait est de rechercher l'élément et d'y ajouter la classe CSS 'unvalidated'.

Utilisation est aussi simple que j'ai toujours voulu:

Exemple:

$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());
}

Pour valider un seul élément:

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

Pour sanatiser un seul élément:

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

La chose la plus cool à propos de cette classe est que vous pouvez envoyer votre formulaire avec une cible ajax ou iframe et exécuter le script résultant. Pas besoin d'actualiser la page ou de renvoyer les mêmes données de formulaire au navigateur :) de plus, si le script a besoin de changer, il n'y a pas de cadre surdimensionné difficile à analyser, il suffit de le changer comme vous le souhaitez:)

Oh oui, n'hésitez pas à l'utiliser où vous voulez. Aucune licence

65
répondu SchizoDuckie 2009-04-10 19:04:15

La réponse de SchizoDuckie ci-dessus était génial. J'ai utilisé son code dans le projet sur lequel je travaille avec la permission de l'auteur. Un problème que j'ai eu en utilisant ce code était que si un champ obligatoire n'était pas soumis, il n'enregistrerait pas d'erreur. J'ai modifié le code pour couvrir ce scénario. J'ai également supprimé le code pour générer HTML et javascript car mon projet exige la séparation de L'interface utilisateur de la logique par modèle MVC. Le code modifié renvoie simplement le résultat codé JSON. Je repost le code modifié ici au cas où il serait utile à d'autres.

<?
/**
* 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;
}           
}
?>
24
répondu John Pendlebury 2011-07-29 17:49:57

Si vous voulez en programmer vous - même et que vous avez PHP 5.2.0 ou supérieur. Ensuite, vous pouvez regarder dans les fonctions de filtre .

12
répondu Ólafur Waage 2009-04-10 11:51:04

Il y a aussi cette bibliothèque sur github: https://github.com/blackbelt/php-validation

8
répondu David d C e Freitas 2011-05-02 09:47:42

Zend Formes, Qui peut être utilisé sans l'ensemble du Zend framework

5
répondu Jonathan 2009-04-10 12:28:33

Il est inclus dans le Code de l'Allumeur cadre, jetez un oeil ici

Je recommande de commencer à utiliser L'un des frameworks PHP ;)

4
répondu Mahtar 2009-04-10 12:05:27

, Vous avez une partie du framework symfony nommé formulaires symfony, qui peut être utilisé en dehors de tout cadre.

Jetez un oeil à la documentation du framework .

2
répondu Rémy 2009-04-10 12:00:10

Ce phpro.org la classe de validation semble très bonne pour une validation facile des données:

Http://www.phpro.org/classes/Validation-Class.html

Il supporte des règles comme la longueur, etc.

0
répondu Priyank Bolia 2012-03-28 10:45:39