检查变量在PHP中是否为整数


78

我有以下代码

    $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()函数正常工作。在网址(noobs.php?p = 1)中输入“ 1”会给我无效的页面错误,以及类似“ asdf”的错误。

Answers:


181

使用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

第二种选择(比较方式):

# 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

10
注意FILTER_VALIDATE_INT(您的首选方式)0返回false!
Niksac 2015年

13
使用filter_var($ int,FILTER_VALIDATE_INT)!== false代替。
Niksac

1
我认为有一个!缺少if(filter_var($variable, FILTER_VALIDATE_INT) !== false) echo "its not an integer,对吗?
亚当

3
或将文本更改为“ it is iteger”
Adam

3
对于负整数,“ CTYPE_DIGIT方式”和“ REGEX方式”均失败。可以通过检查是否有前导负号(-?)来固定“ REGEX方式” ,但是我不认为ctype_digit可以用简洁的方式来检查负整数。同样,发布的代码无法产生相应的输出。
戴夫F

33

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

您可以通过以下方式查看var_dump

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

使用is_numeric将提供所需的结果(请注意,允许使用诸如的值0x24)。


3
警告:这不仅会返回整数,而且会返回true,请使用以下其他解决方案之一。
内森·贝尔


11

只是为了踢球,我测试了一些上述方法,再加上多年以来,当我知道我的输入是正数或等效字符串时,我一直将其用作解决方案。

我用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>";  

8

/!\最佳答案不正确,is_numeric()对于整数和所有数字形式(例如“ 9.1”)返回true

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

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

PS:我知道这是一篇旧文章,但仍是Google中第三条寻找“ php is integer”的文章


1
这是错误的,因为即使例如$ var =“ 9”,此条件也将成立。应该是if((int)$ var === $ var)。$ a == $ b等于TRUE,如果在类型变戏法之后$ a等于$ b。$ a === $ b相同如果$ a等于$ b并且它们是同一类型,则为TRUE。
valerij vasilcenko 2015年

请注意,(int) $var如果不能将字符串转换成数字,它将返回零,因此: (int) 'banana' === 0
Ignacio Segura

因评论表明此答案不正确而被否决。
EAmez

@IgnacioSegura所以,如果在验证器之后使用,它安全if (is_numeric($var) && ((int) $var == $var)) {...}吗?
Guney Ozsan

@GuneyOzsan您的建议听起来很正确,但是老实说,两年前我停止使用PHP进行编码,但我忘了很多东西。抱歉,我没有更多帮助。
Ignacio Segura

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

1
好吧,如果你第一次施展它的整数,然后is_intis_numeric将始终返回true ...
netcoder

2

$_GET始终是字符串,这就是GET参数的含义。因此,is_int($_GET[...])永远是假的。

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



2

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

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

此打印

1a是整数,真的吗?”

使用带有FILTER_VALIDATE_INT参数的filter_var()

$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

我喜欢您的解决方案...接受0,但拒绝非整数字符。
user2662680

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

尝试转换并检查最初是否为数字。


is_int()此处的调用是多余的。$page由于前一行代码的原因,此处的变量始终是整数。
Hammerite

@ netcoder / @ Hammerite:Touche,忘记了强制类型转换将提供默认值。应该检查是否>0。我很抱歉。
布拉德·克里斯蒂

1

当我开始阅读它时,我确实注意到你们忘记了那种像检查类型一样的显而易见的想法,以检查我们是否有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的最简单方法。



0

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

无效的八进制文字

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

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

$var = ltrim($var, 0);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.