Fonction PHP : is_valide()
Ici, vous pouvez voir (et copier/coller) le code complet de la fonction PHP is_valide(). N'hésitez pas voter pour cette fonction si elle vous plaît ou si vous vouv en servez !
is_valide() ajouté le 2009-05-18 17:33:44 par Gafa
/*
Fonction qui retourne vrai si une variable correspond au type donné
type possible :
- IPV4, adresse ip v4
- URL_GLOBAL, une url, sans le http://, et acceptant les sous-domaines
- ISBN, numéro ISBN des livres
- HEXCOLOR_GLOBAL, code hexadécimal d'un couleur, avec ou sans dièse (sur 3 ou 6 caractères)
- HEXCOLOR6#, code hexadécimal d'un couleur, avec dièse (sur 6 caractères)
- HEXCOLOR6, code hexadécimal d'un couleur, sans dièse (sur 6 caractères)
- HEXCOLOR3#, code hexadécimal d'un couleur, avec dièse (sur 3 caractères)
- HEXCOLOR3, code hexadécimal d'un couleur, sans dièse (sur 3 caractères)
- TEL_FR_GLOBAL, numéro de téléphone français (10 chiffres séparés ou pas par point, tiret, slash ou espace)
- TEL_FR, numéro de téléphone français (10 chiffres collés)
- TEL_FR_POINT, numéro de téléphone français (10 chiffres séparés par des points)
- TEL_FR_TIRET, numéro de téléphone français (10 chiffres séparés par des tirets)
- TEL_FR_SLASH, numéro de téléphone français (10 chiffres séparés par des slashs)
- TEL_FR_SPACE, numéro de téléphone français (10 chiffres séparés par des espaces)
- EMAIL, adresse e-mail
- SECU_GLOBAL, numéro de sécurité sociale française (15 chiffres avec ou sans espace)
- SECU, numéro de sécurité sociale française (15 chiffres sans espace)
- SECU_SPACE, numéro de sécurité sociale française (15 chiffres avec espace)
- ZIP_FR, code postal français
- ZIP_US, code postal américain
- DATE_FR, date au format français jj/mm/aaaa
- DATE_US, date au format américain mm/dd/yyyy
*/
function is_valide($ls_variable, $ls_type)
{
switch ($ls_type)
{
case 'IPV4':
$ls_regex = '^([0-9]{1,3}\.){3}[0-9]{1,3}$';
break;
case 'URL_GLOBAL':
$ls_regex = '^[a-zA-Z0-9\-\.]+\.([a-z]{2,6})$';
break;
case 'ISBN':
$ls_regex = '^[0-9]{9}[[0-9]|X|x]$';
break;
case 'HEXCOLOR_GLOBAL':
$ls_regex = '^#?([a-f]|[A-F]|[0-9]){3}(([a-f]|[A-F]|[0-9]){3})?$';
break;
case 'HEXCOLOR6#':
$ls_regex = '^#([a-f]|[A-F]|[0-9]){6}$';
break;
case 'HEXCOLOR6':
$ls_regex = '^([a-f]|[A-F]|[0-9]){6}$';
break;
case 'HEXCOLOR3#':
$ls_regex = '^#([a-f]|[A-F]|[0-9]){3}$';
break;
case 'HEXCOLOR3':
$ls_regex = '^([a-f]|[A-F]|[0-9]){3}$';
break;
case 'TEL_FR_GLOBAL':
$ls_regex = '^0[1-9]([.|-|/| ]?[0-9]{2}){4}$';
break;
case 'TEL_FR':
$ls_regex = '^0[1-9]([0-9]{2}){4}$';
break;
case 'TEL_FR_POINT':
$ls_regex = '^0[1-9]([.][0-9]{2}){4}$';
break;
case 'TEL_FR_TIRET':
$ls_regex = '^0[1-9]([-][0-9]{2}){4}$';
break;
case 'TEL_FR_SLASH':
$ls_regex = '^0[1-9]([/][0-9]{2}){4}$';
break;
case 'TEL_FR_SPACE':
$ls_regex = '^0[1-9]([ ][0-9]{2}){4}$';
break;
case 'EMAIL':
$nonascii = "\x80-\xff"; // non-ASCII not allowed
$nqtext = "[^\\\\$nonascii\015\012\"]";
$qchar = "\\\\[^$nonascii]";
$protocol = '(?:mailto:)';
$normuser = '[a-zA-Z0-9][a-zA-Z0-9_.-]*';
$quotedstring = "\"(?:$nqtext|$qchar)+\"";
$user_part = "(?:$normuser|$quotedstring)";
$dom_mainpart = '[a-zA-Z0-9][a-zA-Z0-9._-]*\\.';
$dom_subpart = '(?:[a-zA-Z0-9][a-zA-Z0-9._-]*\\.)*';
$dom_tldpart = '[a-zA-Z]{2,6}';
$domain_part = "$dom_subpart$dom_mainpart$dom_tldpart";
$ls_regex = "$protocol?$user_part\@$domain_part";
break;
case 'SECU_GLOBAL':
$ls_regex = '^[1|2]([ ]?[0-9]{2}){3}([ ]?[0-9]{3}){2}[ ]?[0-9]{2}$';
break;
case 'SECU':
$ls_regex = '^[1|2]([0-9]{2}){3}([0-9]{3}){2}[0-9]{2}$';
break;
case 'SECU_SPACE':
$ls_regex = '^[1|2]([ ][0-9]{2}){3}([ ][0-9]{3}){2}[ ][0-9]{2}$';
break;
case 'ZIP_FR':
$ls_regex = '^[0-9]{5}$';
break;
case 'ZIP_US':
$ls_regex = '^[0-9]{5}(-[0-9]{4})?$';
break;
case 'DATE_FR':
$ls_regex = '^[0-3][0-9]/[0-1][0-9]/[0-9]{4}$';
break;
case 'DATE_US':
$ls_regex = '^[0-1][0-9]/[0-3][0-9]/[0-9]{4}$';
break;
}
if (mb_ereg($ls_regex, $ls_variable))
{
return true;
}
else
{
return false;
}
}
Une fonction pour les vérifications de formulaires, n'hésitez pas à la compléter...
Commentaires sur la fonctions php
Hugo 18/05/2009 à 19:53
Deux gros inconvénients pour cette fonction :
1. Elle est beaucoup trop longue, elle fait trop de choses. Une fonction doit rester courte et ne faire qu'une seule chose.
2. Avec PHP 5 et son lot de fonctions natives, il est encore dommage de voir des validations à base de regex quand des fonctions dédiées existent déjà (cf extension Filter, fonction ip2long(), checkdate()...)
++
fluminis 18/05/2009 à 23:04
Tres belle fonction, vraiment très utile.
Perso j'utilise une fonction similaire qui en plus permet de :
- prendre un tableau associatif en paramettre pour valider tous les champs d'un formulaire en un seul appel
- gère les champs requis ou non
- gère les messages d'erreur pour tous les champs qui ne remplissent pas les conditions (le parametre $formname est utilisé dans ma gestion des erreurs donc vous pouvez le supprimer selon vos besoin ; et addErrorWithParam() est une fonction gérant mes messages d'erreur pour mon appli)
- ...
En combinant les deux fonctions ca devrait faire une petite bombe ^^
/**
* Check if the required fields are present in the given array
* a number and/or positive
* @param formname name of the form
* @param array $_POST or $_GET for example
* @param required array of required field name
* @return true if all the required fields exist in the array
*/
function verifyFields($formname,$array,$required) {
$ret = true;
$nb_requis = 0;
$all_required = array();
//for all fields
foreach($required as $fieldname => $field) {
if (isset($array[$fieldname])) {
$value = $array[$fieldname];
} else {
$value = "";
}
$str_value = "$value";
if (empty($str_value) && $str_value!="0") {
if (in_array("required",$field)){
//requiered but empty
$all_required[] = lang($formname.'.'.$fieldname);
$ret = false;
$nb_requis++;
}
} else if (in_array("number",$field) && !preg_match('/^-?[0-9]+(\.[0-9]+)?$/',$value)) {
//number
addErrorWithParam($formname,'error.number',lang($formname.'.'.$fieldname));
$ret = false;
} else if (in_array("positive",$field) && $value<0 ) {
//positive
addErrorWithParam($formname,'error.positive',lang($formname.'.'.$fieldname));
$ret = false;
} else if (in_array("alpha",$field) && !preg_match('/^[a-z][a-z ._-]*$/i',$value)) {
//alpha
addErrorWithParam($formname,'error.alpha',lang($formname.'.'.$fieldname));
$ret = false;
} else if (in_array("alpha_accent",$field) && !preg_match('/^[a-zéèêïçùñà][a-zéèêïçùñà ._-]*$/i',$value)) {
//alpha_accent
addErrorWithParam($formname,'error.alpha',lang($formname.'.'.$fieldname));
$ret = false;
} else if (in_array("alphanum",$field) && !preg_match('/^[a-z0-9 ._-]*$/i',$value)) {
//alpha
addErrorWithParam($formname,'error.alpha',lang($formname.'.'.$fieldname));
$ret = false;
} else if (in_array("email",$field) && !preg_match('/^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$/',$value)) {
//alpha
addErrorWithParam($formname,'error.email',lang($formname.'.'.$fieldname));
$ret = false;
// } else if (in_array("website",$field) && !preg_match('/^((http|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?)$/',$value)) {
} else if (in_array("website",$field) && !preg_match('/^((http|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:\/\~\+#]*[\w\-\@?^=%&\/~\+#])?)$/',$value)) {
//url for a web site (not an ftp for emample)
addErrorWithParam($formname,'error.siteperso',lang($formname.'.'.$fieldname));
$ret = false;
}
}
if (count($all_required)<=2) {
foreach($all_required as $val){
addErrorWithParam($formname,'error.required',$val);
}
} else {
addError($formname,'error.fieldsrequired');
}
return $ret;
}
//exemple d'utilisation :
if(verifyFields('myaccount',$_POST,array(
'mylogin' => array('required','alpha'),
'psw1' => array('required'),
'psw2' => array('required'),
'firstname' => array('required','alpha_accent'),
'lastname' => array('required','alpha_accent'),
'ville' => array('alpha'),
'siteperso' => array('website'),
'email' => array('required','email'),
'lang' => array('required','alpha'),
'alert' => array('required','alpha'),
'timezone' => array('required','number'),
'sexe' => array('required','alpha'),
'charte' => array('required','alpha')
))) {
//cool the form is ok
} else {
//error in the form
} Horus 19/05/2009 à 09:52
salut
@Hugo
"Elle est beaucoup trop longue, elle fait trop de choses. Une fonction doit rester courte et ne faire qu'une seule chose."
Où tu as vu ça qu'une fonction doit être courte ? C'est pas plutôt une contrainte que tu t'applique à toi même ?
Dans le fond, je pense effectivement que découpé ta fonction en quelques isEmail(), isCodePostal(), etc... serait plus "ma intenable".
++
Hugo 19/05/2009 à 10:04
@Horus : ça fait partie des bonnes pratiques de développement informatique. Je t'invite à lire des ouvrages dédiés sur le sujet ("Coder proprement" aux éditions Pearson par exemple) ainsi qu'à suivre des études dans le domaine informatique si ce n'est déjà le cas.
Une fonction c'est une petite unité de code qui n'a pour vocation de remplir qu'une et une seule fonction. Lorsqu'une méthode ou une fonction dépasse une vingtaine de lignes, c'est que vraisemblablement il y a un manque de factorisation quelque part...
Horus 19/05/2009 à 13:07
@Hugo
"ainsi qu'à suivre des études dans le domaine informatique si ce n'est déjà le cas."
:) je précise même que c'était le cas, puisque j'ai même fait du développement mon métier aujourd'hui.
Je pense juste que faire de la factorisation pour simplement en faire n'apporte rien.
C'est plus par exemple en terme de temps d'exécution qu'une fonction se "juge". La factorisation n'est qu'un exemple d'optimisation.
Alors oui, je me répète, dans ce cas de validation de formulaire, il aurait été judicieux de faire des fonctions isEmail(), etc...
++
arnaud-k 19/05/2009 à 14:06
@hugo : si tu as des fonctions équivalentes, je t'invite à les proposer ici !
Quand à cette fonction, je serai plutôt du même avis que Horus, rien ne sert de factoriser pour factoriser. Une doit accomplir une seule fonction et pour moi c'est le cas, elle vérifie si le champ est valide.
M'enfin, au final, il y a autant de façon de développer qu'il y a de développeurs !
Mazzu 19/05/2009 à 15:29
@arnaud-k : Voici quelques fonctions qui peuvent servir à faire la même chose :
http://php.net/filter-var
http://php.net/ip2long : «Returns the IPv4 address or FALSE if ip_address is invalid.»
Hugo 19/05/2009 à 16:03
@Horus, la factorisation n'a rien à voir avec l'optimisation. Et l'optimisation dans une fonction, ça ne sert strictement à rien, ou plutôt à pas grand chose. En effet, la génération de ta page côté serveur ne te coûtera quelque millisecondes, soit, à l'échelle humaine, un temps négligeable. En revanche, ce qui prend du temps, c'est le traitement de la page côté client par ton navigateur (css, html, js...). Là, on ne parle plus de millisecondes mais de secondes entières. Donc l'optimisation du code PHP ne sert pratiquement à rien, surtout si ton serveur de production dispose d'une solution de cache d'opcodes telle que APC.
Pour en revenir au sujet principal, cette fonction est mauvaise car elle est difficillement testables unitairement. J'entends par difficilement, le fait qu'il faille écrire beaucoup trop de tests pour chaque cas possible que vérifie la fonction. Et à chaque fois qu'une nouvelle vérification sera implémentée dans la fonction, il faudra ajouter des tests unitaires en plus pour s'assurer qu'elle réagit toujours bien comme on s'y attend.
Avec des toutes petites unités de code séparées (des fonctions courtes donc), les tests unitaires en sont grandement simplifiés puisqu'à chaque petite fonction, on écrira une toute petite série de tests unitaires simples. Au final, le maintien de la fonction final sera grandement simplifié si des tests unitaires propres sont maintenus à jour régulièrement.
Néanmoins là, je m'avance sur des concepts que vous ne connaissez probablement pas ou peu. Je vous invite à vous renseigner sur ces bonnes pratiques de tests unitaires et vous verrez combien il est préférable d'écrire des fonctions simples et courtes, plutôt que des pavés de ce type.
@arnaud : j'utilise les fonctions natives du langage pour ça ou bien des librairies open-source qui ont déjà fait leurs preuves en milieu professionnel. Je ne réinvente pas la roue à chaque fois que je développe une nouvelle application.
Horus 19/05/2009 à 17:50
@Hugo
Bon dernier com' parce qu'au final, on est complètement d'accord sur le fond : cette fonction n'est pas un bon exemple de "bonne" fonction.
Par contre la chose ou l'on est, du coup absolument pas d'accord :
"l'optimisation dans une fonction, ça ne sert strictement à rien, ou plutôt à pas grand chose"
"l'optimisation du code PHP ne sert pratiquement à rien"
Finalement je rectificatif, je suis d'accord avec toi si l'on reste dans le cadre de "petit" développement de site web.
A un autre niveau, cela devient important de s'attarder à l'optimisation du code.
Un simple exemple ou je veux en venir : http://m-fernandez.developpez.com/articles/php/bench/
++
Hugo 19/05/2009 à 20:20
@Horus : oui et ? Ces benchmarks, tout le monde les connaît mais ils ne sont rien représentatif d'une application réelle. Trouve moi une application professionnelle qui a besoin de faire 3 000 000 de fois la même affectation de valeur et on en reparlera. Je suis entièrement d'accord avec les petites optimisations présentées dans ce tutoriel, et cela fait des années que je code de cette manière. Néanmoins, ces optimisations sont presque inutile car elles n'influent pas beaucoup sur le temps d'affichage final d'une page web. Je le rappelle à nouveau, le traitement côté serveur est très rapide. Ce qui est lent en revanche, c'est la génération des pages côté client car il faut prendre en compte la quantité d'informations à télécharger (le code html, le css, le js, les images, les flashs...), la qualité de la bande passante (la connexion Internet) pour le transport de ces données, puis les performances matérielles et logicielles de l'ordinateur pour rendre la page. Au final, la génération du code html côté serveur aura coûté quelques millisecondes, tandis que tout le processus de génération de la page (de la requête HTTP jusqu'à l'affichage dans le navigateur) aura pris 5, 10 secondes, voire beaucoup plus. Donc les quelques millisecondes gagnées ou perdues parce que l'on utilise un guillemet plutôt qu'un apostrophe, on s'en moque radicalement, surtout quand le serveur possède un cache d'opcodes. En revanche, les 5, 10, 20, 60 secondes qu'a mis la page pour s'afficher sur le navigateur, on ne s'en fiche pas car c'est ton utilisateur final qui en pâti. Juste pour information, est-ce que tu mets en application ces quelques bonnes pratiques en plus de tes "optimisations" de PHP ?
- Utilises-tu un CDN (serveur de contenus statiques) pour gérer tes fichiers statiques tels que les images, les flashs... ?
- Compresses-tu tes CSS et JS dans un seul et même fichier ?
- Envoies-tu des entêtes Expires au navigateur ?
- Mets-tu tes pages HTML en cache sur ton serveur ?
- Utilises-tu des sprites pour monter tes pages web ?
- Optimises-tu le poids de tes images ?
- Tous tes sites ont-ils chacun un serveur dédié ?
- ...
Bref, avant de penser "optimisations syntaxiques de php" qui ne servent à rien ou presque au final, il faut d'abord penser aux performances côté client, et donc à l'utilisateur final !
Gafa 20/05/2009 à 10:10
Je me permet de participer à la discussion... :)
1. Oui cette fonction est longue, personnellement je ne m'en sers pas en prod, mais je voulais juste rassembler une liste non exhaustive d'expressions régulières utile pour ne faire qu'un post. Après libre à chacun de ne reprendre que la partie qui l'intéresse...
2. J'ai volontairement omis d'utiliser les filter_var car tout le monde n'utilise pas forcément php 4 (pas bien mais bon...)
Hugo 20/05/2009 à 11:02
"2. J'ai volontairement omis d'utiliser les filter_var car tout le monde n'utilise pas forcément php 4 (pas bien mais bon...)"
Dommage, il faudrait plutôt résonner différemment, à savoir : "tant pis pour ceux qui utilisent encore PHP 4, ils n'ont qu'à migrer leurs applications (trop cher !) ou trouver d'autres codes sources compatibles PHP 4".
Si l'on continue de développer du code encore compatible PHP 4 aujourd'hui alors qu'il y a de meilleures solutions natives en PHP 5, il y a un soucis. Cette logique ne va pas dans le sens de la promotion de PHP 5, au contraire.
Fadhoula 04/09/2010 à 11:25
Salut Gafa, Fluminis & les autres,
A nous autres débutants) , pouvez vous mettre davantge d'explications (en Français SVP) concernant l'usage de ces Fonctions. On est en prèsence de fonctions très riches et insoupsonnables surtout pour la "validation des Données".
En tant qu'ancien coboliste, je veux savoir si une zone de texte saisie, est numérique ou si la taille est de tant de caracteres , ou si la valeur saisie existe dans une Table (un code client par ex.) etc
Merci d'être explicites et clairs
arnaud-k 18/05/2009 à 18:08
Wouah, je suis assez impressionné par celle-là. Elle me paraît bien complète et je sais qu'elle devrait bientôt me servir.