37

Is there a nicer way to do this?

if( $_POST['id'] != (integer)$_POST['id'] )
    echo 'not a integer';

I've tried

if( !is_int($_POST['id']) )

But is_int() doesn't work for some reason.

My form looks like this

<form method="post">
   <input type="text" name="id">
</form>

I've researched is_int(), and it seems that if

is_int('23'); // would return false (not what I want)
is_int(23);   // would return true

I've also tried is_numeric()

is_numeric('23'); // return true
is_numeric(23); // return true
is_numeric('23.3'); // also returns true (not what I want)

it seems that the only way to do this is: [this is a bad way, do not do it, see note below]

if( '23' == (integer)'23' ) // return true
if( 23 == (integer)23 ) // return true
if( 23.3 == (integer)23.3 ) // return false
if( '23.3' == (integer)'23.3') // return false

But is there a function to do the above ?


Just to clarify, I want the following results

23     // return true
'23'   // return true
22.3   // return false
'23.3' // return false

Note: I just figured out my previous solution that I presented will return true for all strings. (thanks redreggae)

$var = 'hello';
if( $var != (integer)$var )
    echo 'not a integer';

// will return true! So this doesn't work either.

This is not a duplicate of Checking if a variable is an integer in PHP, because my requirements/definitions of integer is different than theres.

Community
  • 1
  • 1
Arian Faurtosh
  • 17,987
  • 21
  • 77
  • 115
  • Try RegEXP. `preg_match('/^[\d]*$/',$variable)!==FALSE` – CP510 Oct 07 '13 at 22:18
  • Why do you need to "validate"? Cannot you just filter values? So: $input = (int)$_POST['id'] . This will give you a 100% safe integer (or 0 in case of issues), and it is much easier to handle... – ItalyPaleAle Oct 07 '13 at 22:19
  • @Qualcuno I was thinking about that, but I want to notify the user that they didn't type in a correct number and not change it for them. – Arian Faurtosh Oct 07 '13 at 22:21
  • how about var_dump($_POST["id"]),this will tell you the datatype; – bhawin Oct 07 '13 at 22:22
  • Why? Suppose he/she types "aaa", it will become 0 and you will refuse it the same way as you'd refuse the input 0. (because it's an id, so I suppose it will be > 0). You will just tell your users "wrong input", no need to detail it further! – ItalyPaleAle Oct 07 '13 at 22:23
  • @Qualcuno suppose they type in `23.3` and meant to type in `233`... casting it will truncate it to `23` ... which would be bad. – Arian Faurtosh Oct 07 '13 at 22:25
  • @Arian This is an edge case. Just add some JS on the input field to refuse every non-numeric digit. Server-side checks should be meant more as security measures: for correcting user inputs you could use JS without problems, in my opinion – ItalyPaleAle Oct 07 '13 at 22:29
  • yes..I've clarified that in my edit. "php" == 0 is `true`! – bitWorking Oct 07 '13 at 23:12
  • @redreggae Thanks for catching that! – Arian Faurtosh Oct 07 '13 at 23:14
  • Glad that somebody had already added this post to [web.archive.org](http://web.archive.org/web/*/http://stackoverflow.com/questions/19235746/php-check-to-see-if-variable-is-integer) for preservation. I was going to do it otherwise.. – Fr0zenFyr Aug 31 '15 at 22:08
  • Possible duplicate of [Checking if a variable is an integer in PHP](http://stackoverflow.com/questions/6416763/checking-if-a-variable-is-an-integer-in-php) – Veve Apr 22 '16 at 10:23

12 Answers12

55

try ctype_digit

if (!ctype_digit($_POST['id'])) {
    // contains non numeric characters
}

Note: It will only work with string types. So you have to cast to string your normal variables:

$var = 42;
$is_digit = ctype_digit((string)$var);

Also note: It doesn't work with negative integers. If you need this you'll have to go with regex. I found this for example:

EDIT: Thanks to LajosVeres, I've added the D modifier. So 123\n is not valid.

if (preg_match("/^-?[1-9][0-9]*$/D", $_POST['id'])) {
    echo 'String is a positive or negative integer.';
}

More: The simple test with casting will not work since "php" == 0 is true and "0" === 0 is false! See types comparisons table for that.

$var = 'php';
var_dump($var != (int)$var); // false

$var = '0';
var_dump($var !== (int)$var); // true
bitWorking
  • 12,485
  • 1
  • 32
  • 38
  • 2
    `$integer = 42; ctype_digit($integer);` will return false – aaron Oct 07 '13 at 22:28
  • This is a good solution unless OP needs to support negative integers. – Mike Brant Oct 07 '13 at 22:30
  • 1
    yes..if you check it with "normal" variable and not $_GET or $_POST than first cast to `string`. `$is_digit = ctype_digit((string)42);` – bitWorking Oct 07 '13 at 22:30
  • 3
    @aaron That is correct a string would need to be input. Luckily in case of `$_POST` values, they are always strings. – Mike Brant Oct 07 '13 at 22:31
  • @MikeBrant you're right..negative integers won't work. Than you have to check with regex. Something like `if (!preg_match("/^-?[1-9][0-9]*$/", $_POST['id']))` – bitWorking Oct 07 '13 at 22:36
  • @aaron thanks for letting me know it doesn't work in that case. This is a great solution for $_POST, but there is still no substitute for `$var == (integer)$var`, besides `preg_match` which isn't simpler – Arian Faurtosh Oct 07 '13 at 22:37
  • I don't think there's a need to use those unknown functions in a simple case like this. – Geoffrey Huck Oct 07 '13 at 22:39
  • 1
    @GeoffreyHuck Well, they're not unknown once you've used them... I think `ctype_digit` should be used much more often than `is_numeric`, which has a more memorable name but is rarely actually the test you want to perform. – IMSoP Oct 07 '13 at 22:59
  • In case it matters, both `ctype_digit` and this particular regex will return true for strings containing values way too big for an int. – cHao Oct 07 '13 at 23:15
  • @cHao I cannot verify that. Which PHP version are you using? – bitWorking Oct 07 '13 at 23:20
  • @cHao I've tested it with really big integer strings and it works. So there seems to be no casting to integer involved?! – bitWorking Oct 07 '13 at 23:23
  • @redreggae: Currently? None. I don't need an interpreter to see this, though. `ctype_digit('1234567890123456789012345678901234567890')` will return `true`. That means it's lying about whether the string would be a valid int. – cHao Oct 07 '13 at 23:24
  • @cHao because it is an integer..so where is the problem? `ctype_digit('1234567890123456789012345678901234567890a')` will return `false` which is correct. – bitWorking Oct 07 '13 at 23:25
  • @cHao ok got you..I think this is beyond the question. If you're doing your math with BCMath it doesn't matter. It really depends on what the OP is doing with his integers. – bitWorking Oct 07 '13 at 23:29
  • 1
    You need the D modifier to the preg_match. And it doesn't accept the 0 to number. – Lajos Veres Oct 08 '13 at 07:50
  • @LajosVeres hmm..the D modifier makes no difference for me. can you give an example? And I kinda like it that it doesn't accept leading zeros. – bitWorking Oct 08 '13 at 10:49
  • Sorry but without line breaks it is not really nice... The main idea is that trailing \n will be accepted without D. $ php5 -r 'preg_match("/^-?[1-9][0-9]*$/","123\n") && print "accepted\n";' accepted $ php5 -r 'preg_match("/^-?[1-9][0-9]*$/D","123\n") && print "accepted\n";' $ – Lajos Veres Oct 08 '13 at 11:14
17

try filter_var function

filter_var($_POST['id'], FILTER_VALIDATE_INT);

use:

if(filter_var($_POST['id'], FILTER_VALIDATE_INT)) { 
    //Doing somethings...

}
Dũng IT
  • 2,751
  • 30
  • 29
9

In PHP $_POST values are always text (string type).

You can force a variable into the integer type like this:

$int_id = (int)$_POST['id'];

That will work if you are certain that $_POST['id'] should be an integer. But if you want to make absolutely sure that it contains only numbers from 0 to 9 and no other signs or symbols use:

if( ctype_digit( $_POST['id'] ) )
{
  $int_id = (int)$_POST['id'];
}
Sébastien
  • 11,860
  • 11
  • 58
  • 78
3

Using is_numeric() for checking if a variable is an integer is a bad idea. This function will send TRUE for 3.14 for example. It's not the expected behavior

To do this correctly, you can use one of these options :

Considering this variables array :

$variables = [
    "TEST 0" => 0,
    "TEST 1" => 42,
    "TEST 2" => 4.2,
    "TEST 3" => .42,
    "TEST 4" => 42.,
    "TEST 5" => "42",
    "TEST 6" => "a42",
    "TEST 7" => "42a",
    "TEST 8" => 0x24,
    "TEST 9" => 1337e0
];

The first option (FILTER_VALIDATE_INT Way) :

# Check if your variable is an integer
if( ! filter_var($variable, FILTER_VALIDATE_INT) ){
  echo "Your variable is not an integer";
}

Output :

TEST 0 : 0 (type:integer) is not an integer ✘
TEST 1 : 42 (type:integer) is an integer ✔
TEST 2 : 4.2 (type:double) is not an integer ✘
TEST 3 : 0.42 (type:double) is not an integer ✘
TEST 4 : 42 (type:double) is an integer ✔
TEST 5 : 42 (type:string) is an integer ✔
TEST 6 : a42 (type:string) is not an integer ✘
TEST 7 : 42a (type:string) is not an integer ✘
TEST 8 : 36 (type:integer) is an integer ✔
TEST 9 : 1337 (type:double) is an integer ✔

The second option (CASTING COMPARISON Way) :

# Check if your variable is an integer
if ( strval($variable) != strval(intval($variable)) ) {
  echo "Your variable is not an integer";
}

Output :

TEST 0 : 0 (type:integer) is an integer ✔
TEST 1 : 42 (type:integer) is an integer ✔
TEST 2 : 4.2 (type:double) is not an integer ✘
TEST 3 : 0.42 (type:double) is not an integer ✘
TEST 4 : 42 (type:double) is an integer ✔
TEST 5 : 42 (type:string) is an integer ✔
TEST 6 : a42 (type:string) is not an integer ✘
TEST 7 : 42a (type:string) is not an integer ✘
TEST 8 : 36 (type:integer) is an integer ✔
TEST 9 : 1337 (type:double) is an integer ✔

The third option (CTYPE_DIGIT Way) :

# Check if your variable is an integer
if( ! ctype_digit(strval($variable)) ){
  echo "Your variable is not an integer";
}

Output :

TEST 0 : 0 (type:integer) is an integer ✔
TEST 1 : 42 (type:integer) is an integer ✔
TEST 2 : 4.2 (type:double) is not an integer ✘
TEST 3 : 0.42 (type:double) is not an integer ✘
TEST 4 : 42 (type:double) is an integer ✔
TEST 5 : 42 (type:string) is an integer ✔
TEST 6 : a42 (type:string) is not an integer ✘
TEST 7 : 42a (type:string) is not an integer ✘
TEST 8 : 36 (type:integer) is an integer ✔
TEST 9 : 1337 (type:double) is an integer ✔

The fourth option (REGEX Way) :

# Check if your variable is an integer
if( ! preg_match('/^\d+$/', $variable) ){
  echo "Your variable is not an integer";
}

Output :

TEST 0 : 0 (type:integer) is an integer ✔
TEST 1 : 42 (type:integer) is an integer ✔
TEST 2 : 4.2 (type:double) is not an integer ✘
TEST 3 : 0.42 (type:double) is not an integer ✘
TEST 4 : 42 (type:double) is an integer ✔
TEST 5 : 42 (type:string) is an integer ✔
TEST 6 : a42 (type:string) is not an integer ✘
TEST 7 : 42a (type:string) is not an integer ✘
TEST 8 : 36 (type:integer) is an integer ✔
TEST 9 : 1337 (type:double) is an integer ✔
Cam CHN
  • 3,377
  • 1
  • 19
  • 12
2

Check it out: http://php.net/manual/en/function.ctype-digit.php - it validates if string contains only digits, so be sure not to pass an int to that function as it will most likely return false; However all values coming from $_POST are always strings so you are safe. Also it will not validate negative number such as -18 since - is not a digit, but you can always do ctype_digit(ltrim($number, '-'))

is_int checks the variable type which in your case is string; it would be the same as (integer)$v === $v as == does some real obscure things in order to compare two variables of a different type; you should always use === unless you want mess like "0af5gbd" == 0 to return true

Also, keep in mind that ctype_digit will not tell you if the string can be actually converted to a valid int since maximum integer value is PHP_INT_MAX; If your value is bigger than that, you will get PHP_INT_MAX anyway.

Adam Zielinski
  • 2,774
  • 1
  • 25
  • 36
2
preg_match('/^\d+$/D',$variable) //edit 
Lajos Veres
  • 13,595
  • 7
  • 43
  • 56
2

if you know it is a string variable (like post o get values), you can use:

function is_really_integer($var) {
  return $var == (string)(integer)$var;
}
glerendegui
  • 1,457
  • 13
  • 15
1

The accepted answer using ctype_digit is correct, however you can make life easier using a function. This will covert the variable to a string, so you don't have to:

function is_num($x){
    if(!is_string($x)){
        $x=(string)$x;
    }
    if(ctype_digit($x)){
      return true;
    }
    return false;
}

Usage:

if (is_num(56)) {
    // its a number
}

if (is_num('56')) {
    // its a number
}

If you want to accept decimals too, use this:

function is_num($x){
    if(!is_string($x)){
        $x=(string)$x;
    }    
    if (strpos($x,'.')!==false) {      
        if(substr_count($x,'.')>1||strpos($x,'.')<1||strpos($x,'.')>=strlen($x)){
            return false;    
        }
        $x=str_replace('.','',$x);    
    }
    if(ctype_digit($x)){
        return true;
    }  
    return false;
}
David D
  • 1,269
  • 17
  • 22
1

Use filter_var but be careful it's return bool.

In case you have string '0' => you will get false

Right way to use:

if (filter_var($_POST['id'], FILTER_VALIDATE_INT) !== false) { 
    // Doing somethings...
}
AlSan
  • 383
  • 5
  • 9
0

Use the following, universal function to check all types:

function is_digit($mixed) {
    if(is_int($mixed)) {
        return true;
    } elseif(is_string($mixed)) {
        return ctype_digit($mixed);
    }

    return false;
}
Andreas
  • 2,821
  • 25
  • 30
0

I use:

is_int($val)||ctype_digit($val)

Note than this catch only positive integer strings

Luca C.
  • 11,714
  • 1
  • 86
  • 77
0

is_int is perfectly working there is not need of extra code

or you can check using is_numeric

Juned Ansari
  • 5,035
  • 7
  • 56
  • 89