Проверка, является ли переменная целым числом в 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.РНР?p=1) дает мне ошибку недопустимой страницы, а также что-то вроде "asdf".

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 ✔

четвертый вариант (REGEX way):

# 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. всегда будет возвращать false.

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


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

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

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

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


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

Я проверил это со 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

(я даже не проверить регулярное выражение, я имею в виду, серьезно... regex для этого?)

Примечание:
Метод 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 всегда строки-это то, что получают парамтеры. Следовательно,is_int($_GET[...]) всегда false.

вы можете проверить, состоит ли строка только из цифр (т. е. может быть интерпретирована как число) с 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);