PHP에서 변수가 정수인지 확인


80

다음 코드가 있습니다.

    $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 () 함수가 제대로 작동하지 않는 것 같습니다. URL (noobs.php? p = 1)에 "1"을 넣으면 "asdf"와 같은 잘못된 페이지 오류가 발생합니다.

답변:


184

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

10
FILTER_VALIDATE_INT (선호하는 방법)에주의하십시오. 0은 false를 반환합니다!
Niksac

13
대신 filter_var ($ int, FILTER_VALIDATE_INT)! == false를 사용하십시오.
Niksac 2015

1
나는 생각한다! 에서 if(filter_var($variable, FILTER_VALIDATE_INT) !== false) echo "its not an integer빠졌지?
아담

3
또는 텍스트를`it is an iteger`로 변경해야합니다
Adam

3
'CTYPE_DIGIT 방식'과 'REGEX 방식'은 모두 음의 정수에 대해 실패합니다. 'REGEX 방식'은 선행 음수 부호 ( -?) ctype_digit가 있는지 확인하여 수정할 수 있지만 음의 정수를 확인하기 위해 간결하게 사용할 수 있다고 생각하지 않습니다 . 또한 게시 된 코드는 해당 출력을 생성 할 수 없습니다.
Dave F

33

모든 $_GET매개 변수에는 문자열 데이터 유형이 있으므로 is_int항상 false를 리턴합니다.

다음을 호출하여 확인할 수 있습니다 var_dump.

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

를 사용 is_numeric하면 원하는 결과를 얻을 수 있습니다 (예 :) 0x24.


3
경고 : 이것은 int 이상에 대해 true를 반환하므로 아래 다른 솔루션 중 하나를 사용하십시오.
Nathan Bell


12

킥을 위해 언급 된 방법 중 몇 가지를 테스트하고 입력이 양수 또는 문자열과 동등한 것을 알 때 수년 동안 솔루션으로 사용했습니다.

나는 이것을 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_int하고 ctype_digit정수가 있는지 확인하는 것이 거의 두 배 빠른 것 같습니다. 변수가 문자열이고 첫 번째 문자가 대시 일 때 방법 5로 대체하는 방법 1을 사용하는 것이 그 다음으로 빠른 것입니다 (특히 입력의 대부분이 실제 정수이거나 문자열의 양수인 경우). 대체로 견고한 일관성이 필요하고 데이터의 혼합이 무엇인지 알지 못하고 일관된 방식으로 부정적인 것을 처리해야하는 경우 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

/! \ Best anwser가 올바르지 않습니다. is_numeric ()은 정수 및 "9.1"과 같은 모든 숫자 형식에 대해 true를 반환합니다.

정수의 경우에만 친숙하지 않은 preg_match ( '/ ^ \ d + $ /', $ var) 또는 명시적이고 2 배 빠른 비교를 사용할 수 있습니다.

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

추신 : 나는 이것이 오래된 게시물이지만 여전히 "php is integer"를 찾는 Google에서 세 번째라는 것을 알고 있습니다.


1
예를 들어 $ var = "9"인 경우에도이 조건이 참이기 때문에 이것은 잘못된 것입니다. if ((int) $ var === $ var)이어야합니다. $ a == $ b 같음 유형 저글링 후 $ a가 $ b와 같으면 참. $ a === $ b 동일 $ a가 $ b와 같고 동일한 유형이면 TRUE입니다.
valerij vasilcenko 2015

통지 (int) $var문자열이 될 수없는 경우, 그래서 숫자로 0을 반환합니다 : (int) 'banana' === 0
이그나시오 구라

댓글이이 답변이 옳지 않음을 드러내면서 반대표를 던졌습니다.
EAmez

@IgnacioSegura와 같은 유효성 검사기 후에 사용하면 안전 if (is_numeric($var) && ((int) $var == $var)) {...}합니까?
Guney Ozsan

@GuneyOzsan 당신이 제안한 것은 옳게 들리지만 솔직히 말해서 2 년 전에 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 2011-06-20

@ netcoder / @ Hammerite : Touche, 캐스트가 기본값을 제공한다는 것을 잊었습니다. 확인해야합니다 >0. 죄송합니다.
Brad Christie

1

내가 그것을 읽기 시작했을 때 나는 우리가 int, string, null 또는 Boolean이 있는지 확인하기 위해 type of와 같은 명백한 생각을 잊었다는 것을 알았습니다. 그래서 나는 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

0으로 시작하는 정수는 8 진수 문자로 해석 될 수 있으므로 PHP 7부터 치명적인 오류를 발생시킵니다.

유효하지 않은 8 진 리터럴

이전에는 유효하지 않은 숫자가 포함 된 8 진 리터럴이 자동으로 잘 렸습니다 (0128은 012로 간주 됨). 이제 유효하지 않은 8 진 리터럴로 인해 구문 분석 오류가 발생합니다.

따라서 먼저 정수에서 선행 0을 제거 할 수 있습니다.

$var = ltrim($var, 0);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.