Подтвердить что ты не робот

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

4b9b3361

Ответ 1

Использование 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 way):

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

Ответ 2

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

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

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

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

Ответ 3

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

Вместо этого попробуйте is_numeric() или ctype_digit()

Ответ 4

/!\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"

Ответ 5

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

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

Ответ 6

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

$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

Ответ 7

Значения $_GET всегда являются строками – что GET paramters приходят как. Поэтому is_int($_GET[...]) всегда false.

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

Ответ 8

У меня была аналогичная проблема только сейчас!

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

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

Ответ 9

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

Попробуйте выполнить кастинг и проверить, действительно ли это номер.

Ответ 10

Решение

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

Ответ 12

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

Недопустимые восьмеричные литералы

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

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

$var = ltrim($var, 0);

Ответ 13

Когда я начал читать его, я заметил, что вы, ребята, забыли о неожиданном типе типа проверки, чтобы проверить, есть ли у нас int, string, null или Boolean. Так что я думаю, что gettype() должен быть 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

Я думаю, что это самый простой способ проверить, является ли наша переменная int, string, double или Boolean.