检查变量是否是PHP中的整数

时间:2011-06-20 20:02:51

标签: php

我有以下代码

    $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

我将用它来查看数据库的不同“页面”(结果1-10,11-20等)。但是,我似乎无法使is_int()函数正常工作。将“1”放入url(noobs.php?p = 1)会给我带来无效的页面错误,以及类似“asdf”的内容。

13 个答案:

答案 0 :(得分:149)

使用is_numeric()检查变量是否为整数是一个坏主意。例如,此函数将为TRUE返回3.14。这不是预期的行为。

要正确执行此操作,您可以使用以下选项之一:

考虑这个变量数组:

$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
];

第一个选项(FILTER_VALIDATE_INT方式):

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

输出:

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 ✔

第二个选项(CASTING COMPARISON方式):

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

输出:

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 ✔

第三个选项(CTYPE_DIGIT方式):

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

输出:

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 ✔

第四个选项(REGEX方式):

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

输出:

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 ✔

答案 1 :(得分:31)

所有$_GET参数都有字符串数据类型,因此is_int将始终返回false。

您可以致电var_dump

来查看此内容
var_dump($_GET['p']); // string(2) "54"

使用is_numeric会提供所需的结果(请注意,它允许使用以下值:0x24)。

答案 2 :(得分:23)

当浏览器在查询字符串中发送p时,它将作为字符串而不是int接收。因此,is_int()将始终返回false。

而是尝试is_numeric()ctype_digit()

答案 3 :(得分:9)

/!\ Best anwser不正确,is_numeric()为整数和所有数字形式返回true,如“9.1”

仅对于整数,您可以使用不友好的preg_match('/ ^ \ d + $ /',$ var)或显式和快2倍的比较:

if ((int) $var == $var) {
    // $var is an integer
}
PS:我知道这是一个老帖子,但仍然是谷歌寻找“php is integer”的第三个

答案 4 :(得分:6)

只是为了踢,我测试了一些提到的方法,加上一个我用作解决方案多年的时候我知道我的输入是正数或字符串等效。

我用125,000次迭代测试了这个,每次迭代都传递了相同的变量类型和值集。

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

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

(我甚至没有测试正则表达式,我的意思是,认真地......正则表达式?)

需要注意的事项:
对于负数(负整数或字符串等效),方法4总是返回false,因此这是一种一致检测值是正整数的好方法。
方法1对于负整数返回true,但对于等于负整数的字符串返回false,因此除非您确定输入永远不会包含字符串或整数形式的负数,否则不要使用此方法,如果确实如此,你的过程不会打破这种行为。

<强>结论
因此,如果您确定您的输入不包含负数,那么使用is_intctype_digit来验证您有一个整数的速度几乎快两倍。当变量是一个字符串并且第一个字符是破折号时,使用方法1回退到方法5是下一个最快的(特别是当大多数输入是实际整数或字符串中的正数时)。总而言之,如果你需要坚实的一致性,并且你不知道数据的混合是什么,并且你必须以一致的方式处理否定,filter_var($value, FILTER_VALIDATE_INT) !== FALSE获胜。

用于获取上述输出的代码:

$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>";  

答案 5 :(得分:3)

您可以尝试使用强制转换运算符将其转换为整数:

$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

答案 6 :(得分:2)

$_GET总是字符串 - 这就是GET参数的来源。因此,is_int($_GET[...])始终为假。

您可以使用is_numeric测试字符串是否只包含数字(即可以解释为数字)。

答案 7 :(得分:2)

我刚才有类似的问题!

您可以将filter_input()功能与FILTER_VALIDATE_INTFILTER_NULL_ON_FAILURE一起使用,仅过滤$_GET变量中的整数值。工作非常准确! :)

点击此处查看我的问题:How to check whether a variable in $_GET Array is an integer?

答案 8 :(得分:1)

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

尝试投射并检查它是否是最初的数字。

答案 9 :(得分:1)

doctormad的解决方案不正确。试试这个:

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

打印

  

1a是一个整数,真的吗?“

filter_var() FILTER_VALIDATE_INT 参数一起使用

$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");
});

打印

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

答案 10 :(得分:0)

使用is_int($var)

Here is tutorial about is_int()

答案 11 :(得分:0)

从PHP开始,以0开头的整数将导致致命错误,因为它可能会将其解释为八进制字符。

  

八进制文字无效

     

以前,包含无效数字的八进制文字是   默默地截断(0128被视为012)。现在,一个无效的八进制   literal将导致解析错误。

因此,您可能希望从整数中删除前导零,首先:

$var = ltrim($var, 0);

答案 12 :(得分:0)

当我开始阅读它的时候,我确实注意到你们忘了那种像检查类型一样的想法,我们是否检查过int,string,null或Boolean。 所以我认为gettype()应该是第一答案。 说明: 因此,如果我们有$test = [1,w2,3.45,sasd];,我们就开始对其进行测试

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";
        }
}

并输出:

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

我认为这是检查var是int,string,double还是Boolean的最简单方法。