web-dev-qa-db-fra.com

PHP is_numeric ou preg_match 0-9 validation

Ce n’est pas un gros problème pour moi (à ma connaissance), c’est plutôt quelque chose qui m’intéresse. Mais quelle est la principale différence, le cas échéant, entre is_numeric plus de preg_match (ou vice versa) pour valider les valeurs entrées par l'utilisateur.

Exemple un:

<?php
    $id = $_GET['id'];
    if (!preg_match('/^[0-9]*$/', $id)) {
        // Error
    } else {
        // Continue
    }
?>

Exemple deux:

<?php
    $id = $_GET['id'];
    if (!is_numeric($id)) {
        // Error
    } else {
        // Continue
    }
?>

Je suppose que les deux font exactement la même chose, mais y a-t-il des différences spécifiques qui pourraient causer des problèmes ultérieurement? Existe-t-il un "meilleur moyen" ou quelque chose que je ne vois pas qui les rend différents?.

35
no.

is_numeric() teste si une valeur est un nombre. Cela ne doit pas nécessairement être un entier, il peut s'agir d'un nombre décimal ou d'un nombre en notation scientifique.

L'exemple preg_match() que vous avez donné vérifie uniquement qu'une valeur contient les chiffres de zéro à neuf; un nombre quelconque d'entre eux, et dans n'importe quelle séquence.

Notez que l'expression régulière que vous avez donnée n'est pas non plus un vérificateur d'entiers parfait, comme vous l'avez écrit. Cela ne permet pas les négatifs; il permet une chaîne de longueur nulle (c'est-à-dire sans chiffres du tout, ce qui ne devrait probablement pas être valide?), et permet au nombre d'avoir un nombre quelconque de zéros non significatifs, ce qui peut ne pas être le cas.

[MODIFIER]

Selon votre commentaire, une meilleure expression régulière pourrait ressembler à ceci:

/^[1-9][0-9]*$/

Cela force le premier chiffre à se situer uniquement entre 1 et 9, vous ne pouvez donc pas avoir de zéros en tête. Cela l'oblige également à être long d'au moins un chiffre, ce qui résout le problème de chaîne de longueur nulle.

Vous n'êtes pas inquiet pour les négatifs, donc ce n'est pas un problème.

Vous voudrez peut-être limiter le nombre de chiffres car, dans l’état actuel des choses, les chaînes trop volumineuses seront stockées sous forme d’entiers. Pour restreindre cela, vous changeriez l'étoile en une restriction de longueur comme ceci:

/^[1-9][0-9]{0,15}$/

Cela permettrait à la chaîne d'avoir entre 1 et 16 chiffres (c'est-à-dire le premier chiffre plus 0-15 autres chiffres). N'hésitez pas à ajuster les chiffres entre les accolades pour répondre à vos propres besoins. Si vous voulez une chaîne de longueur fixe, il vous suffit de spécifier un nombre entre les accolades.

J'espère que ça t'as aidé.

61
Spudley

Selon http://www.php.net/manual/en/function.is-numeric.php , is_numeric autorise quelque chose comme "+ 0123.45e6" ou "0xFF". Je pense que ce n'est pas ce que vous attendez.

preg_match peut être lent et vous pouvez avoir quelque chose comme 0000 ou 0051.

Je préfère utiliser ctype_digit (ne fonctionne qu'avec des chaînes, c'est correct avec $ _GET).

<?php
  $id = $_GET['id'];
  if (ctype_digit($id)) {
      echo 'ok';
  } else {
      echo 'nok';
  }
?>
11
rap-2-h

is_numeric () autorise toute forme de nombre. donc 1, 3.14159265, 2.71828e10 sont tous "numériques", alors que votre expression rationnelle se réduit à l'équivalent de is_int()

7
Marc B

is_numeric accepterait "-0.5e + 12" comme identifiant valide.

5
user187291

Pas exactement pareil.

De la PHP docs de is_numeric:

'42' is numeric
'1337' is numeric
'1e4' is numeric
'not numeric' is NOT numeric
'Array' is NOT numeric
'9.1' is numeric

Avec votre regex, vous ne vérifiez que les valeurs numériques "de base".

De plus, is_numeric() devrait être plus rapide.

5
PeeHaa

is_numeric vérifie s'il s'agit d'un nombre quelconque, tandis que votre expression rationnelle vérifie s'il s'agit d'un entier, éventuellement précédé de 0. Pour un identifiant, stocké sous la forme d'un entier, il est fort probable que nous voudrons ne pas avoir de 0 en tête. Après la réponse de Spudley, nous pouvons faire:

/^[1-9][0-9]*$/

Cependant, comme le note Spudley, la chaîne résultante est peut-être trop grande pour être stockée sous forme de valeur entière 32 bits ou 64 bits. La valeur maximale d'un nombre entier signé de 32 bits est de 2 147 483 647 (10 chiffres) et la valeur maximale d'un nombre entier signé de 64 bits est de 9 223 372,036,854,775,807 (19 chiffres). Cependant, de nombreux nombres entiers à 10 et 19 chiffres sont plus grands que les nombres entiers maximum 32 bits et 64 bits respectivement. Une solution simple, uniquement pour regex, serait:

/^[1-9][0-9]{0-8}$/ 

ou

/^[1-9][0-9]{0-17}$/

respectivement, mais ces "solutions" se limitent malheureusement à des nombres entiers de 9 et 19 chiffres; résultat difficilement satisfaisant. Une meilleure solution pourrait être quelque chose comme:

$expr = '/^[1-9][0-9]*$/';
if (preg_match($expr, $id) && filter_var($id, FILTER_VALIDATE_INT)) {
    echo 'ok';
} else {
    echo 'nok';
}
5
Jacob Lee

is_numeric vérifie plus:

Détermine si la variable donnée est numérique. Les chaînes numériques se composent d'un signe optionnel, d'un nombre quelconque de chiffres, d'une partie décimale optionnelle et d'une partie exponentielle optionnelle. Ainsi, + 0123.45e6 est une valeur numérique valide. La notation hexadécimale (0xFF) est également autorisée, mais uniquement sans signe, partie décimale et exponentielle.

3
MasterCassim

Vous pouvez utiliser ce code pour la validation du numéro:

if (!preg_match("/^[0-9]+$/i", $phone)) {
        $errorMSG = 'Invalid Number!';
        $error    = 1;
    }
1
vicky mahale

La fonction is_numeric de PHP autorise les flottants ainsi que les entiers. En même temps, la fonction is_int est trop stricte si vous souhaitez valider les données de formulaire (chaînes uniquement). Par conséquent, vous avez généralement intérêt à utiliser des expressions régulières pour cela.

À proprement parler, les nombres entiers sont des nombres entiers positifs et négatifs, y compris zéro. Voici une expression régulière pour cela:

/ ^ 0 $ | ^ [-]? [1-9] [0-9] * $ /

OU, si vous souhaitez autoriser les zéros non significatifs:

/ ^ [-]? [0] | [1-9] [0-9] $ /

Notez que cela autorisera des valeurs telles que -0000, ce qui ne pose cependant pas de problème en PHP. (MySQL transmettra également des valeurs telles que 0.)

Vous pouvez également vouloir limiter la longueur de votre entier pour des considérations de 2/64-bit PHP fonctionnalités de la plate-forme) et/ou la compatibilité de la base de données. Par exemple, pour limiter la longueur de votre entier à 9 chiffres (sauf le signe facultatif -), vous pouvez utiliser:

/ ^ 0 $ | ^ [-]? [1-9] [0-9] {0,8} $ /

1
mixabo

Si vous uniquement vérifiez s'il s'agit d'un nombre, is_numeric() vaut beaucoup beaucoup mieux ici. C'est plus lisible et un peu plus rapide que regex.

Le problème avec votre regex ici est qu'il n'autorisera pas les valeurs décimales, vous avez donc essentiellement écrit is_int() dans regex. Les expressions régulières ne doivent être utilisées que s'il existe un format de données non standard dans votre entrée; PHP possède de nombreuses fonctions de validation intégrées, même un validateur d'email sans regex .

1
Bojangles

En attendant, toutes les valeurs ci-dessus limiteront uniquement les valeurs à un nombre entier, donc j’utilise

/^[1-9][0-9\.]{0,15}$/

pour autoriser les valeurs float aussi.

0
tormuto