Checking if a variable is an integer in PHP

Php

Php Problem Overview


I have the following code

	$page = $_GET['p'];
	
	if($page == "")
	{
		$page = 1;
	}
	if(is_int($page) == false)
	{
		setcookie("error", "Invalid page.", time()+3600);
		header("location:somethingwentwrong.php");
		die();
	}
    //else continue with code

which I am going to use for looking at different "pages" of a database (results 1-10, 11-20, etc). I can't seem to get the is_int() function to work correctly, however. Putting "1" into the url (noobs.php?p=1) gives me the invalid page error, as well as something like "asdf".

Php Solutions


Solution 1 - Php

Using is_numeric() for checking if a variable is an integer is a bad idea. This function will return 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) === false ) {
  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 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

Solution 2 - Php

All $_GET parameters have a string datatype, therefore, is_int will always return false.

You can see this by calling var_dump:

var_dump($_GET['p']); // string(2) "54"

Using is_numeric will provide the desired result (mind you, that allows values such as: 0x24).

Solution 3 - Php

When the browser sends p in the querystring, it is received as a string, not an int. is_int() will therefore always return false.

Instead try is_numeric() or ctype_digit()

Solution 4 - Php

Just for kicks, I tested out a few of the mentioned methods, plus one I've used as my go to solution for years when I know my input is a positive number or string equivalent.

I tested this with 125,000 iterations, with each iteration passing in the same set of variable types and values.

Method 1: is_int($value) || ctype_digit($value)
Method 2: (string)(int)$value == (string)$value
Method 3: strval(intval($value)) === strval($value)
Method 4: ctype_digit(strval($value))
Method 5: filter_var($value, FILTER_VALIDATE_INT) !== FALSE
Method 6: is_int($value) || ctype_digit($value) || (is_string($value) && $value[0] === '-' && filter_var($value, FILTER_VALIDATE_INT) !== FALSE)

Method 1: 0.0552167892456
Method 2: 0.126773834229
Method 3: 0.143012046814
Method 4: 0.0979189872742
Method 5: 0.112988948822
Method 6: 0.0858821868896

(I didn't even test the regex, I mean, seriously... regex for this?)

Things to note:
Method 4 always returns false for negative numbers (negative integer or string equivalent), so is a good method to consistently detect that a value is a positive integer.
Method 1 returns true for a negative integer, but false for a string equivalent of a negative integer, so don't use this method unless you are certain your input will never contain a negative number in string or integer form, and that if it does, your process won't break from this behavior.

Conclusions
So it seems that if you are certain that your input will not include a negative number, then it is almost twice as fast to use is_int and ctype_digit to validate that you have an integer. Using Method 1 with a fallback to method 5 when the variable is a string and the first character is a dash is the next fastest (especially when a majority of the input is actual integers or positive numbers in a string). All in all, if you need solid consistency, and you have no idea what the mix of data is coming in, and you must handle negatives in a consistent fashion, filter_var($value, FILTER_VALIDATE_INT) !== FALSE wins.

Code used to get the output above:

$u = "-10";
$v = "0";
$w = 0;
$x = "5";
$y = "5c";
$z = 1.44;

function is_int1($value){
    return (is_int($value) || ctype_digit($value));
}

function is_int2($value) {
    return ((string)(int)$value == (string)$value);
}

function is_int3($value) {
    return (strval(intval($value)) === strval($value));
}

function is_int4($value) {
    return (ctype_digit(strval($value)));
}

function is_int5($value) {
    return filter_var($value, FILTER_VALIDATE_INT) !== FALSE;
}

function is_int6($value){
    return (is_int($value) || ctype_digit($value) || (is_string($value) && $value[0] === '-' && filter_var($value, FILTER_VALIDATE_INT)) !== FALSE);
}

$start = microtime(TRUE);
for ($i=0; $i < 125000; $i++) {
  is_int1($u);
  is_int1($v);
  is_int1($w);
  is_int1($x);
  is_int1($y);
  is_int1($z);
}
$stop = microtime(TRUE);
$start2 = microtime(TRUE);
for ($j=0; $j < 125000; $j++) {
  is_int2($u);
  is_int2($v);
  is_int2($w);
  is_int2($x);
  is_int2($y);
  is_int2($z);
}
$stop2 = microtime(TRUE);
$start3 = microtime(TRUE);
for ($k=0; $k < 125000; $k++) {
  is_int3($u);
  is_int3($v);
  is_int3($w);
  is_int3($x);
  is_int3($y);
  is_int3($z);
}
$stop3 = microtime(TRUE);
$start4 = microtime(TRUE);
for ($l=0; $l < 125000; $l++) {
  is_int4($u);
  is_int4($v);
  is_int4($w);
  is_int4($x);
  is_int4($y);
  is_int4($z);
}
$stop4 = microtime(TRUE); 

$start5 = microtime(TRUE);
for ($m=0; $m < 125000; $m++) {
  is_int5($u);
  is_int5($v);
  is_int5($w);
  is_int5($x);
  is_int5($y);
  is_int5($z);
}
$stop5 = microtime(TRUE); 

$start6 = microtime(TRUE);
for ($n=0; $n < 125000; $n++) {
  is_int6($u);
  is_int6($v);
  is_int6($w);
  is_int6($x);
  is_int6($y);
  is_int6($z);
}
$stop6 = microtime(TRUE); 

$time = $stop - $start;  
$time2 = $stop2 - $start2;  
$time3 = $stop3 - $start3;  
$time4 = $stop4 - $start4;  
$time5 = $stop5 - $start5;  
$time6 = $stop6 - $start6;  
print "**Method 1:** $time <br>";
print "**Method 2:** $time2 <br>";
print "**Method 3:** $time3 <br>";
print "**Method 4:** $time4 <br>";  
print "**Method 5:** $time5 <br>";  
print "**Method 6:** $time6 <br>";  

Solution 5 - Php

/!\ Best anwser is not correct, is_numeric() returns true for integer AND all numeric forms like "9.1"

For integer only you can use the unfriendly preg_match('/^\d+$/', $var) or the explicit and 2 times faster comparison :

if ((int) $var == $var) {
    // $var is an integer
}

PS: i know this is an old post but still the third in google looking for "php is integer"

Solution 6 - Php

doctormad's solution is not correct. try this:

$var = '1a';
if ((int) $var == $var) {
    var_dump("$var is an integer, really?");
}

this prints > 1a is an integer, really?"

use filter_var() with FILTER_VALIDATE_INT argument

$data = Array('0', '1', '1a', '1.1', '1e', '0x24', PHP_INT_MAX+1);
array_walk($data, function ($num){
$is_int = filter_var($num, FILTER_VALIDATE_INT);
if ($is_int === false)
var_dump("$num is not int");
});

this prints

1a is not int 
1.1 is not int
1e is not int
0x24 is not int
9.2233720368548E+18 is not int

Solution 7 - Php

Values $_GET are always strings – that's what GET paramters come as. Therefore, is_int($_GET[...]) is always false.

You can test if a string consists only of digits(i.e. could be interpreted as a number) with http://php.net/is_numeric"><strong>is_numeric</strong></a>;.

Solution 8 - Php

I had a similar problem just now!

You can use the filter_input() function with FILTER_VALIDATE_INT and FILTER_NULL_ON_FAILURE to filter only integer values out of the $_GET variable. Works pretty accurately! :)

Check out my question here: https://stackoverflow.com/questions/12194205/how-to-check-whether-a-variable-in-get-array-is-an-integer

Solution 9 - Php

When i start reading it i did notice that you guys forgot about abvious think like type of to check if we have int, string, null or Boolean. So i think gettype() should be as 1st answer. Explain: So if we have $test = [1,w2,3.45,sasd]; we start test it

foreach ($test as $value) {
        $check = gettype($value);
        if($check == 'integer'){
            echo "This var is int\r\n";
        }
        if($check != 'integer'){
            echo "This var is {$check}\r\n";
        }
}

And output:

> This var is int 
> This var is string 
> This var is double 
> This var is string

I think this is easiest way to check if our var is int, string, double or Boolean.

Solution 10 - Php

You could try using a casting operator to convert it to an integer:

$page = (int) $_GET['p'];

if($page == "")
{
    $page = 1;
}
if(empty($page) || !$page)
{
    setcookie("error", "Invalid page.", time()+3600);
    header("location:somethingwentwrong.php");
    die();
}
//else continue with code

Solution 11 - Php

$page = (isset($_GET['p']) ? (int)$_GET['p'] : 1);
if ($page > 0)
{
  ...
}

Try casting and checking if it's a number initially.

Solution 12 - Php

An integer starting with 0 will cause fatal error as of PHP 7, because it might interpret it as an octal character.

> Invalid octal literals > > Previously, octal literals that contained invalid numbers were > silently truncated (0128 was taken as 012). Now, an invalid octal > literal will cause a parse error.

So you might want to remove leading zeros from your integer, first:

$var = ltrim($var, 0);

Solution 13 - Php

In my opinion the correct function should look as following:

    public function checkIfValueIsInt($value): bool
{
    if (is_bool($value)) {
        return false;
    }

    if (0 === filter_var($value, FILTER_VALIDATE_INT) || filter_var($value, FILTER_VALIDATE_INT)) {
        return true;
    }

    return false;
}

given set of tests is validated correctly using it:

        [
            true,
            false,
        ],
        [
            false,
            false,
        ],
        [
            'false',
            false,
        ],
        [
            'true',
            false,
        ],
        [
            'some random string',
            false,
        ],
        [
            [],
            false,
        ],
        [
            ['some string', 1],
            false,
        ],
        [
            (object) [],
            false,
        ],
        [
            2.222,
            false,
        ],
        [
            rand(0, 99999),
            true,
        ],
        [
            1,
            true,
        ],
        [
            0,
            true,
        ],
        [
            -1,
            true,
        ],

the reason I added is_bool check is that

> true

value is handle incorrectly by:

0 === filter_var($value, FILTER_VALIDATE_INT) || filter_var($value, FILTER_VALIDATE_INT)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionahotaView Question on Stackoverflow
Solution 1 - PhpCam CHNView Answer on Stackoverflow
Solution 2 - PhpTim CooperView Answer on Stackoverflow
Solution 3 - PhpMichael BerkowskiView Answer on Stackoverflow
Solution 4 - PhpJonathan FalknerView Answer on Stackoverflow
Solution 5 - Phpjob3dot5View Answer on Stackoverflow
Solution 6 - PhpAleksandrView Answer on Stackoverflow
Solution 7 - PhpphihagView Answer on Stackoverflow
Solution 8 - Phpmaxxon15View Answer on Stackoverflow
Solution 9 - PhpPiotr MiroszView Answer on Stackoverflow
Solution 10 - PhpDrewdinView Answer on Stackoverflow
Solution 11 - PhpBrad ChristieView Answer on Stackoverflow
Solution 12 - PhpLucas BustamanteView Answer on Stackoverflow
Solution 13 - PhpTomasz WuView Answer on Stackoverflow