2010-05-17 2 views
1

Qu'est-ce qu'un moyen efficace de gérer la validation des données, par exemple, à partir d'une soumission de formulaire?Effective Data Validation

À l'origine, j'avais un tas de if instructions qui vérifiaient chaque valeur et collectaient des valeurs non valides dans un tableau pour une récupération ultérieure (et une liste).

// Store errors here 
$errors = array(); 

// Hypothetical check if a string is alphanumeric 
if (!preg_match('/^[a-z\d]+$/i', $fieldvalue)) 
{ 
    $errors[$fieldname] = 'Please only use letters and numbers for your street address'; 
} 

// etc... 

Ce que je faisais à côté était créer une classe qui gère les différents scénarios de validation de données et stocker les résultats dans un tableau interne. Après la validation des données est complète, je vérifie pour voir si des erreurs se sont produites et des comportements appropriés:

class Validation 
{ 
    private $errorList = array(); 

    public function isAlphaNumeric($string, $field, $msg = '') 
    { 
     if (!preg_match('/^[a-z\d]+$/i', $string)) 
     { 
      $this->errorList[$field] = $msg; 
     } 
    } 

    // more methods here 

    public function creditCard($cardNumber, $field, $msg = '') 
    { 
     // Validate credit card number 
    } 

    // more methods here 

    public function hasErrors() 
    { 
     return count($this->errorList); 
    } 
} 

/* Client code */ 

$validate = new Validation(); 
$validate->isAlphaNumeric($fieldvalue1, $fieldname1, 'Please only use letters and numbers for your street address'); 
$validate->creditCard($fieldvalue2, $fieldname2, 'Please enter a valid credit card number'); 

if ($validate->hasErrors()) 
{ 
    // Handle as appropriate 
} 

Naturellement, il n'a pas fallu longtemps avant que cette classe est devenue pléthorique avec les types quasi illimitées de données à valider. Ce que je fais maintenant utilise décorateurs pour séparer les différents types de données dans leurs propres classes et les appeler uniquement en cas de besoin en laissant les validations génériques (c.-à-isAlphaNumeric()) dans la classe de base:

class Validation 
{ 
    private $errorList = array(); 

    public function isAlphaNumeric($string, $field, $msg = '') 
    { 
     if (!preg_match('/^[a-z\d]+$/i', $string)) 
     { 
      $this->errorList[$field] = $msg; 
     } 
    } 

    // more generic methods here 

    public function setError($field, $msg = '') 
    { 
     $this->errorList[$field] = $msg; 
    } 

    public function hasErrors() 
    { 
     return count($this->errorList); 
    } 
} 

class ValidationCreditCard 
{ 
    protected $validate; 

    public function __construct(Validation $validate) 
    { 
     $this->validate = $validate; 
    } 

    public function creditCard($cardNumber, $field, $msg = '') 
    { 
     // Do validation 
     // ... 
     // if there is an error 
     $this->validate->setError($field, $msg); 
    } 

    // more methods here 
} 

/* Client code */ 

$validate = new Validation(); 
$validate->isAlphaNumeric($fieldvalue, $fieldname, 'Please only use letters and numbers for your street address'); 

$validateCC = new ValidationCreditCard($validate); 
$validateCC->creditCard($fieldvalue2, $fieldname2, 'Please enter a valid credit card number'); 

if ($validate->hasErrors()) 
{ 
    // Handle as appropriate 
} 

Suis-je sur la bonne piste? Ou ai-je compliqué la validation des données plus que nécessaire?

+0

I utilise également la même façon que vous avez décrite dans le dernier. Je serais également intéressé à obtenir la réponse de ce Ques. Currenlty aussi je valide un formulaire. J'utilise TryParse et d'autres fonctions inbuild jusqu'à ce que ce soit possible. Restant je me crée. –

Répondre

2

Si quelque chose, vous ne validez pas assez. Pour la lecture de données dans $ _POST et $ _GET dont vous avez besoin au moins:

  • Pour vérifier si elle existe (array_key_exists)
  • Pour vérifier si c'est un tableau ou non
  • Si attendant UTF-8, vérifiez si il est valide UTF-8 (preg_match avec le « u » modificateur est une option)
  • Ensuite, faites la validation spécifique au type de champ

par ailleurs, le chemin de la hanche en cours pour faire la validation et aseptisation en PHP est d'utiliser filters. Dans votre cas, voici un exemple:

<?php 
$data = array(
    "arg1good" => "sdgdf790", 
    "arg1bad" => "sdgdf7/90", 
    "arg1bad2" => array("sdgdf90", "sfdssf"), 
    "arg2good" => "4567576456", 
    "arg2bad" => "45675764561", 
); 

$validateCredCard = function ($cc) { 
    if (preg_match('/^\\d{10}$/', $cc)) 
     return $cc; 
    else 
     return false; 
}; 

$arg1filt = array('filter' => FILTER_VALIDATE_REGEXP, 
        'flags' => FILTER_REQUIRE_SCALAR, 
        'options' => array('regexp' => '/^[a-z\d]+$/i'), 
       ); 
$arg2filt = array('filter' => FILTER_CALLBACK, 
        'flags' => FILTER_REQUIRE_SCALAR, 
        'options' => $validateCredCard, 
       ); 
$args = array(
    "arg1good" => $arg1filt, 
    "arg1bad" => $arg1filt, 
    "arg1bad2" => $arg1filt, 
    "arg2good" => $arg2filt, 
    "arg2bad" => $arg2filt, 
); 

var_dump(filter_var_array($data, $args)); 

donne:

array(5) { 
    ["arg1good"]=> 
    string(8) "sdgdf790" 
    ["arg1bad"]=> 
    bool(false) 
    ["arg1bad2"]=> 
    bool(false) 
    ["arg2good"]=> 
    string(10) "4567576456" 
    ["arg2bad"]=> 
    bool(false) 
} 
0

Cela me semble trop compliqué.

données numériques: il suffit de jeter la valeur

$val=(int)$_POST["val"]; 

$ _POST Les e-mails: il y a des fonctions premade qui le font (l'espoir de trouver un bon).

$email=check_email($_POST["email"]) or die("Ha!"); 

noms et adresses: ne rien faire, car il viendra le jour où un étranger entre un caractère unicode vous ne pensez pas et être filtrés par votre fonction.

Numéros de téléphone: ne rien faire, s'il veut donner un faux numéro, il le fera de toute façon.

Codes spéciaux, tels que le code postal et d'autres choses de ce genre: vous aurez généralement une norme très stricte, créez une fonction qui filtre en utilisant celle-là et vous avez terminé.

1

Vous ne semblez pas être très clair sur ce que vos objectifs sont - la performance?simplicité du nouveau code? maintenabilité globale? Certes, pour des raisons de performances, je suggère de conserver les validations sous forme de code plutôt que de stocker des expressions rationnelles (et des seuils, et ....) en tant que données. Le problème semble être comment vous mapper les éléments de données que vous avez les validations appropriées. Vous pouvez configurer une carte statique en tant que tableau, car vous devez également connaître la structure de données pour afficher les formulaires et les mapper avec les colonnes de base de données. Vous devriez peut-être envisager de mettre en place une méthode plus formelle de gestion des métadonnées. .

C.

0

@ Lo'oris Votre réponse au sujet de casting les valeurs ne sont pas tout à fait complète. S'il vous plaît considérer l'exemple suivant:

$val_1 = (int)null; // $val_1 equals 0 
$val_2 = (int)false; // $val_2 equals 0 
$val_3 = (int)'';  // $val_3 equals 0 
$val_4 = (int)array(); // $val_4 equals 0 

Comme cet exemple montre, cette stratégie ne fonctionne que si vous attendez que la variable soit un entier qui est aussi supérieure à 0.

En termes de « check_email "fonctions - vous avez raison de dire que de nombreuses implémentations peuvent être trouvées sur Internet, mais la plupart d'entre elles sont incomplètes ou incorrectes.

La plupart des implémentations utilisent des expressions regex comme celui-ci:

"^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$" 

ou celui-ci:

"^[a-zA-Z0-9_.-][email protected][a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$" 

et les deux ces regexes rejettent les adresses électroniques comme celles-ci:

Abc\@[email protected] 
customer/[email protected] 
!def!xyz%[email protected] 

qui sont tous valide (selon http://www.linuxjournal.com/article/9585?page=0,0).

S'il vous plaît ont aussi un oeil à: http://www.regular-expressions.info/email.html

+0

Je ne comprends pas ce que vous voulez dire à propos du casting: oui, ces valeurs incorrectes seront lancées à 0 ... bien pour moi! Si "vous" avez besoin de quelque chose de plus strict, comme> 0, eh bien, dites-le simplement, et ne faites que le coder, ce n'est pas quelque chose d'exotique qui doit être expliqué ... –