web-dev-qa-db-fra.com

Comment vérifier qu'une chaîne est un int, mais pas un double, etc.?

PHP a une fonction intval() qui convertira une chaîne en un entier. Cependant, je souhaite vérifier au préalable que la chaîne est un entier, afin de pouvoir donner un message d'erreur utile à l'utilisateur s'il est erroné. PHP a is_int()], mais cela retourne false pour une chaîne comme "2".

PHP a la fonction is_numeric(), mais elle retournera true si le nombre est un double. Je veux quelque chose qui va retourner faux pour un double, mais vrai pour un int.

par exemple.:

my_is_int("2") == TRUE
my_is_int("2.1") == FALSE
136
Rory

Que diriez-vous d'utiliser ctype_digit ?

Du manuel:

<?php
$strings = array('1820.20', '10002', 'wsl!12');
foreach ($strings as $testcase) {
    if (ctype_digit($testcase)) {
        echo "The string $testcase consists of all digits.\n";
    } else {
        echo "The string $testcase does not consist of all digits.\n";
    }
}
?>

L'exemple ci-dessus affichera:

 La chaîne 1820.20 ne comprend pas tous les chiffres. 
 La chaîne 10002 est composée de tous les chiffres. 
 La chaîne wsl! 12 ne comprend pas tous les chiffres. 

Cela ne fonctionnera que si votre entrée est toujours une chaîne:

$numeric_string = '42';
$integer        = 42;

ctype_digit($numeric_string);  // true
ctype_digit($integer);         // false

Si votre entrée est de type int, combinez ctype_digit Avec is_int .

Si vous vous souciez des nombres négatifs, vous devrez alors vérifier l'entrée pour un précédent -, Et si c'est le cas, appelez ctype_digit Sur un substr de la chaîne d'entrée. Quelque chose comme ça le ferait:

function my_is_int($input) {
  if ($input[0] == '-') {
    return ctype_digit(substr($input, 1));
  }
  return ctype_digit($input);
}
164
Dominic Rodger

filter_var devrait le faire:

var_dump(filter_var('2', FILTER_VALIDATE_INT));   // 2
var_dump(filter_var('2.0', FILTER_VALIDATE_INT)); // false
var_dump(filter_var('2.1', FILTER_VALIDATE_INT)); // false

mais

var_dump(filter_var(2, FILTER_VALIDATE_INT));     // 2
var_dump(filter_var(2.0, FILTER_VALIDATE_INT));   // 2
var_dump(filter_var(2.1, FILTER_VALIDATE_INT));   // false

Si vous souhaitez uniquement des valeurs booléennes comme valeurs de retour, intégrez-les dans une fonction, par exemple.

function validatesAsInt($number)
{
    $number = filter_var($number, FILTER_VALIDATE_INT);
    return ($number !== FALSE);
}
79
Gordon

+1 à la réponse de Dominic (en utilisant ctype_digit). Une autre façon de le faire est d'utiliser la contrainte de type:

$inty = "2";
$inty2 = " 2";
$floaty = "2.1";
$floaty2 = "2.0";

is_int($inty + 0); // true
is_int($floaty + 0); // false
is_int($floaty2 + 0); // false

// here's difference between this and the ctype functions.
is_int($inty2 + 0);  // true
ctype_digit($inty2); // false
18
nickf

Jetez-le à int. s'il a toujours la même valeur, son int;

function my_is_int($var) {
  $tmp = (int) $var;
  if($tmp == $var)
       return true;
  else
       return false;
}
12
greg
/**
 * Check if a number is a counting number by checking if it
 * is an integer primitive type, or if the string represents
 * an integer as a string
 */
function is_int_val($data) {
    if (is_int($data) === true) return true;
    if (is_string($data) === true && is_numeric($data) === true) {
        return (strpos($data, '.') === false);
    }
}

Source .

7
GmonC

Avait besoin d'un robuste is_int récemment. J'ai trouvé intval () trop imprévisible:

intval(array('foo', 'bar')) //returns 1 ?!?
intval("2dog") //returns 2 even though the value is definitely not an integer
intval("dog2") //also returns 2


Nous sommes tombés sur cet extrait dans les PHP de la documentation, et après l'avoir testé, il couvre presque tout ce que vous lui lancez:

function my_is_int($s) {
    return (is_numeric($s) ? intval($s) == $s : false);
}


my_is_int(2); //true
my_is_int("2"); //true
my_is_int(2.1); //false
my_is_int("2.1"); //false
my_is_int("dog"); //false
my_is_int("2dog"); //false
my_is_int("dog2"); //false
my_is_int(array('foo', 'bar')); //false
my_is_int(array(1)); //false


Mais attention:

my_is_int(2.0); //true
my_is_int("2.0"); //true
6
Costa
function my_is_int($var) {
    return preg_match('/^\d+$/', $var);
}
4
Michael Connor

Une façon vraiment propre que j'aime utiliser est celle-là. Vous le lancez deux fois, d'abord dans int, ensuite dans string, puis vous comparez strictement ===. Voir l'exemple ci-dessous:

$value === (string)(int)$value;

Maintenant, à propos de votre fonction my_is_int, vous pouvez faire quelque chose comme ceci:

function my_is_int($value){ return $value === (string)(int)$value; }
my_is_int('2');  // true
my_is_int('2.1') // false
4
Jonathan Gagne

Vous pouvez simplement vérifier le nombre, s'il est vérifié que le casting est doublé ou non:

((is_numeric($var) && !is_double(1*$var)));

Juste pour les nombres positifs:

(is_numeric($var) && !is_double(1*$var)) && ($var >= 0)

En le vérifiant:

$numbersToCheck = array("a", "-1", "1", "1.0", "1.2");

foreach ($numbersToCheck as $var) {
    echo $var . " is integer? ";var_dump((is_numeric($var) && !is_double(1*$var)));

    echo $var . " is a positive integer? ";var_dump((is_numeric($var) && !is_double(1*$var)) && ($var >= 0));
}

Sortie:

a is integer? bool(false)
a is a positive integer? bool(false)
-1 is integer? bool(true)
-1 is a positive integer? bool(false)
1 is integer? bool(true)
1 is a positive integer? bool(true)
1.0 is integer? bool(false)
1.0 is a positive integer? bool(false)
1.2 is integer? bool(false)
1.2 is a positive integer? bool(false)
3
Jordi Martínez

J'utilise celui-ci:

function isInt($val){

    return (filter_var($val, FILTER_VALIDATE_INT) !== false && strpos($val, '-') === false);

}

var_dump (isInt("1"));
3
julesdude
function my_is_int($var){
    return is_numeric($var) && gettype($var+0)=='integer';
}
2
grant sun

Essaye ça:

$string='12abc';
if ((int)$string==$string) var_dump((int)$string); else echo 'Invalid!';
// Outputs: Invalid!

$string='789';
if ((int)$string==$string) var_dump((int)$string); else echo 'Invalid!';
// Outputs: int 789

$string='345.00';
if ((int)$string==$string) var_dump((int)$string); else echo 'Invalid!';
// Outputs: 345

$string='123.01';
if ((int)$string==$string) var_dump((int)$string); else echo 'Invalid!';
// Outputs: Invalid!

Fonctionne également si votre chaîne $ a des décimales

2
Jack M.

Cela prendra en charge le nombre négatif aussi

function myIsInt()
{
   return (is_numeric($var) AND (is_int($var) OR ctype_digit(trim($var, '-'))))
}
//'234-' => false
//'-234' => true
//'--234' => false
//'234' => true
2
wolakpaul

Peut-être pas la manière la plus performante de le faire. Mais vous pouvez l'écrire sur une ligne.

function my_is_int($input) {
    return intval($input).'' === $input.'';
}

Comme prévu:

    my_is_int(1);     // TRUE
    my_is_int(-1);    // TRUE
    my_is_int(1.2);   // FALSE
    my_is_int("1");   // TRUE
    my_is_int("-1");  // TRUE
    my_is_int("1.2"); // FALSE
    my_is_int(0);     // TRUE
    my_is_int(null);  // FALSE

Je t'ai eu:

    my_is_int(1.0);   // TRUE
    my_is_int("1.0"); // FALSE
2
mwallisch

Quelques années plus tard, mais en me basant sur les réponses fournies ici, j'ai proposé une solution légèrement plus précise (sur les booléens en particulier) et plus efficace (je pense) que la plupart des autres réponses:

function my_is_int($s) {
    return ctype_digit($s) || is_int($s);
}

Travailler comme prévu pour ceux-ci:

my_is_int(2);                   // true
my_is_int("2");                 // true
my_is_int(-2);                  // true
my_is_int(2.0);                 // false
my_is_int("2.0");               // false
my_is_int(2.1);                 // false
my_is_int("2.1");               // false
my_is_int("dog");               // false
my_is_int("2dog");              // false
my_is_int("dog2");              // false
my_is_int(array('foo', 'bar')); // false
my_is_int(array(1));            // false
my_is_int(true);                // false
my_is_int(false);               // false
my_is_int("true");              // false
my_is_int("false");             // false
my_is_int("0x101010");          // false

Sauf peut-être pour ces 2:

my_is_int(0x101010);            // true
my_is_int("-2");                // false
2
SharkWipf
public static function isNumeric($value, $negativ = false) {
    return is_int($value) || is_string($value) && (
        ctype_digit($value) || (
            $negativ && $value{0} == '-' && ctype_digit(substr($value, 1))
        )
    );

    //alternativ:
    //return $value == (int) $value;
}
1
Volker

J'ai imaginé un moyen que je ne pouvais trouver nulle part, alors je le mets ici:

Sans plus tarder, c'est ceci: ctype_digit((string) abs($input))

Exemple:

function means_int($input) {
    return ctype_digit((string) abs($input));
}

$list = array(
    0,
    '0',
    1,
    '1',
    1.1,
    '1.1',
    2.0,
    '2.0',  
    2.6,
    '2.6',
    -4,
    '-4',   
    -3.2,
    '-3.2',
    -30.02,
    '-30.02',   
    100.00,
    '100.00',   
);

foreach ($list as $x) {
    var_dump($x);
    var_dump(means_int($x));
    echo PHP_EOL;
}

Résultats: (sont comme prévu, je suppose)

int(0)
bool(true)

string(1) "0"
bool(true)

int(1)
bool(true)

string(1) "1"
bool(true)

float(1.1)
bool(false)

string(3) "1.1"
bool(false)

float(2)
bool(true)

string(3) "2.0"
bool(true)

float(2.6)
bool(false)

string(3) "2.6"
bool(false)

int(-4)
bool(true)

string(2) "-4"
bool(true)

float(-3.2)
bool(false)

string(4) "-3.2"
bool(false)

float(-30.02)
bool(false)

string(6) "-30.02"
bool(false)

float(100)
bool(true)

string(6) "100.00"
bool(true)
1
Smuuf

Que diriez-vous:

function isIntStr($str) {
   return preg_match('/^(-?\d+)(?:\.0+)?$/', trim($str), $ms)
       && bcComp($ms[1], PHP_INT_MAX) <= 0
       && bcComp($ms[1], -PHP_INT_MAX - 1) >= 0;
}

Cette fonction ne doit renvoyer true que pour tout numéro de chaîne pouvant être transtypé en int avec (int) Ou intval() sans rien perdre de sa signification mathématique (comme les non-zéros après le point décimal ou les nombres en dehors de). La plage entière de PHP) tout en acceptant des éléments non significatifs (tels que les espaces; les zéros non significatifs; ou, après le point décimal, uniquement les zéros).

Il retournera false pour '10.' Mais pas pour '10.0'. Si vous voulez que '10.' Soit vrai, vous pouvez changer le + Après le 0 Dans l'expression régulière en *.

1
user2923827

Vous pouvez utiliser la condition suivante. Notez que vous ne devriez pas utiliser! ==

$value = 12; // true
$value = '12'; // true
$value = 'abc'; // false
$value = 12.1; // false
$value = '12.1'; // false

if (!is_numeric($value) || (int) $value != (float) $value) {
    echo "false";
} else {
    echo "true";
}
1
Saman Shafigh

Voici un code que j'ai utilisé qui semble bien fonctionner et ne présente aucun des problèmes que beaucoup d'autres ont.

if (0 != strlen(str_replace(range(0, 9), '', $TestInt))) { print 'Not an integer!';}

Il ne vérifie pas l’ordre, etc., il ne s’agit donc pas d’entiers négatifs, mais d’un code d’addition qui peut également être utilisé en utilisant certaines des idées précédentes. Il peut également être adapté pour fonctionner avec les fonctions binaires array('0', '1') ou hexadécimales, etc.

1
Dragonaire

Regarde ça. Convertit $ val en entier, puis vérifie si le $ val d'origine converti en chaîne est IDENTICAL (===) - seulement == ne fonctionnera pas comme prévu - en val de nombre entier converti en chaîne.

function validInt($val, $min=null, $max=null) {
    $ival = intval($val);
    //echo "'$ival' '$val'<br>\n"; // Uncomment to see the comparisons done in below if block
    if(''.$ival !== ''.$val) {
        return false;
    }
    if($min !== null && $ival < $min)
        return false;
    if($max !== null && $ival > $max)
        return false;
    return true;
}

Si vous ne vérifiez pas les valeurs de chaîne, il se peut que cela ne fonctionne pas comme prévu:

$nums = array(
    '1',
    '+1',
    '-1',
    '01',
    '1.0',
    '.0',
    '1.123',
    'a123',
    '0x101010',
    1,
    -1,
    01,
    1.0,
    .0,
    1.123,
    0x101010,
);
foreach($nums as $num) {
    if(validInt2($num))
        echo $num." - Valid integer.<br>\n";
    else
        echo $num." - Not a valid integer.<br>\n";
}

Sortie:

1 - Valid integer.
+1 - Not a valid integer.
-1 - Valid integer.
01 - Not a valid integer.
1.0 - Not a valid integer.
.0 - Not a valid integer.
1.123 - Not a valid integer.
a123 - Not a valid integer.
0x101010 - Not a valid integer.
1 - Valid integer.
-1 - Valid integer.
1 - Valid integer.
1 - Valid integer.
0 - Valid integer.
1.123 - Not a valid integer.
1052688 - Valid integer.

Raison d'être même si vous utilisez hex (0x101010), octal (01) ou un entier stocké en tant que float (1.0, 0.0), tous sont stockés en interne en tant que float. Cependant, si vous utilisez la fonction pour vérifier que int est stocké sous forme de chaîne, cela fonctionnera.

1
Joe

Voici une solution simple qui utilise is_numeric , floatval , et intval :

function is_string_an_int($string)
{
    if (is_string($string) === false)
    {
        //throw some kind of error, if needed
    }

    if (is_numeric($string) === false || floatval(intval($string)) !== floatval($string))
    {
        return false;
    }

    else
    {
        return true;
    }
}

Résultats:

is_string_an_int('-1'); //true
is_string_an_int('-1.0'); //true
is_string_an_int('-1.1'); //false
is_string_an_int('0'); //true
is_string_an_int('0.0'); //true
is_string_an_int('0.1'); //false
is_string_an_int('1'); //true
is_string_an_int('1.0'); //true
is_string_an_int('1.1'); //false
is_string_an_int('' . PHP_INT_MAX); //true
is_string_an_int('foobar'); //false
is_string_an_int('NaN'); //false
is_string_an_int('null'); //false
is_string_an_int('undefined'); //false

Notez que les valeurs supérieures à PHP_INT_MAX peuvent renvoyer false.

0
Pikamander2

Si vous manipulez des identifiants numériques depuis mysql et tentez d’imposer une validation pour que ce soit un non valide int ou un int mais au format chaîne (comme mysql retourne toujours tout au format chaîne) et non pas NULL. Vous pouvez utiliser ce qui suit. C’est le moyen le plus sûr de ne pas autoriser int/string-ints que j'ai trouvé.

...
if(empty($id) || !is_scalar($id) || !ctype_digit($id)){
  throw("Invalid ID");
}
...
0
Mohd Abdul Mujib

Si vous voulez réellement savoir si une chaîne est une représentation valide d'un vrai PHP type entier ...

in_array($string, array_map('strval', range(PHP_INT_MIN, PHP_INT_MAX)), true)

Cependant, il est impossible de l'exécuter car le jeu est trop volumineux (dans ce cas, la mémoire ne tiendra pas, si vous bouclez, cela prendra trop de cycles CPU).

Vous pouvez peut-être faire une recherche binaire avec une comparaison de chaînes, mais il existe de meilleurs moyens.

Le plus simple étant:

strlen($string) <= max(strlen((string)PHP_INT_MIN), strlen((string)PHP_INT_MAX)) && $string === (string)(int)$string

Il existe d'autres manières inhabituelles de l'aborder, telles que:

is_int(array_keys([$string => null])[0])

Vous pouvez également faire une comparaison de chaînes, mais vous devrez tout de même faire des choses telles que ctype_digit, vérifier que la longueur est raisonnable (ne gaspillez pas le processeur avant de faire des choses comme ctype_digit) et maîtriser les nombres négatifs.

Notez que filter_var (pas) affirme correctement qu'une chaîne de caractères est véritablement la représentation d'un PHP entier. Elle autorisera un + et les espaces adjacents environnants.

En interne PHP utilise la fonction "_zend_handle_numeric_str" pour une comparaison stricte, mais ne l'expose pas directement, d'où l'astuce utilisant les clés array (qui l'utilise pour convertir toute chaîne qui est une représentation de a PHP entier à un PHP entier)].

Si vous voulez une conversion binaire sûre vers et à partir de PHP), c'est l'approche à adopter.

Tout le monde ne voudra peut-être pas cela et il faudra peut-être gérer les entrées de l'utilisateur. filter_var n'est pas trop mauvais pour cela et sera assez sûr dans la plupart des cas pour les débutants en PHP.

Une vérification de la longueur, ctype_digit, puis une vérification de la valeur convertie dans une plage est également assez solide pour une entrée utilisateur. Des schémas plus complexes peuvent vouloir couper ou regex.

Le problème avec beaucoup de réponses ici à cet égard est que, même si la question est vague, les réponses ne devraient pas l'être. Si vous proposez une solution, vous devriez être en mesure d’expliquer exactement ce qu’elle fera et ce à quoi elle ne s’attendra pas. Sans cela, il est impossible de savoir si une réponse correspond à une question ou si elle est sûre. Le manuel PHP) n’aide pas toujours car il n’explique pas toutes les mises en garde relatives à chacune des méthodes fournies, ctype_digit et is_int sont très fiables et faciles à prédit, mais les spécificités de is_numeric, filter_var et jonglerie (+ $ var) ou casting (intval/floatval) sont mal documentées.

Il s’agit d’un fudge PHP pour vous. Il contient une myriade de schémas permettant d’interpréter les chaînes en tant qu’entiers, avec des incohérences. La méthode la plus stricte de validation d’une chaîne entière n’est pas directement exposée à l’utilisateur.

0
jgmjgm