Проверка, является ли переменная целым числом в 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".

12 52
php

12 ответов:

используя 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 ✔

четвертый вариант (регулярное выражение):

# 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 ✔

все $_GET параметры имеют строковый тип данных, поэтому is_int всегда будет возвращать false.

вы можете увидеть это, позвонив var_dump:

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

используя is_numeric обеспечит желаемый результат (имейте в виду, что позволяет такие значения, как: 0x24).

когда браузер посылает p в строке запроса он принимается как строка, а не int. is_int() поэтому всегда будет возвращать false.

вместо is_numeric() или ctype_digit()

/!\ Best anwser не является правильным, is_numeric () возвращает true для целого числа и всех числовых форм, таких как "9.1"

только для целого числа вы можете использовать недружественный preg_match ('/^\d+$/', $var) или явное и в 2 раза более быстрое сравнение:

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

PS: Я знаю, что это старый пост, но все же третий в google ищет "php is integer"

просто для удовольствия, я протестировал несколько из упомянутых методов, плюс один, который я использовал в качестве своего решения в течение многих лет, когда я знаю, что мой вход является положительным числом или строковым эквивалентом.

Я проверил это с помощью 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 чтобы проверить, что у вас есть целое число. Использование метода 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>";  

вы можете попробовать использовать оператор литья, чтобы преобразовать его в целое число:

$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

значения $_GET всегда строки-это то, что получить paramters приходят как. Таким образом, is_int($_GET[...]) всегда ложно.

Вы можете проверить, если строка состоит только из цифр(т. е. может быть интерпретировано как число) с is_numeric.

у меня была подобная проблема только сейчас!

можно использовать с FILTER_VALIDATE_INT и FILTER_NULL_ON_FAILURE для фильтрации только целочисленных значений из $_GET переменной. Работает довольно точно! :)

проверьте мой вопрос здесь: Как проверить, является ли переменная в массиве $_GET целым числом?

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

попробуйте кастинг и проверить, если это число изначально.

решение 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

использовать is_int($var)

вот учебник о is_int()

целое число, начинающееся с 0, вызовет фатальную ошибку с PHP 7, потому что оно может интерпретировать его как восьмеричный символ.

недействительным восьмеричные литералы

ранее восьмеричные литералы, содержащие недопустимые числа, были молча усекается (0128 был принят за 012). Теперь, недействительный восьмеричный литерал вызовет ошибку синтаксического анализа.

таким образом, вы можете удалить ведущие нули из вашего целого числа, во-первых:

$var = ltrim($var, 0);