Проверка целого числа в PHP: от is_int до регулярных выражений
В разработке на PHP часто требуется проверить, является ли значение целым числом. Это может быть необходимо для валидации данных, ввода пользователя, математических операций. Существует несколько способов, каждый со своими особенностями.
Проверка целого числа в PHP
Самый эффективный способ - использование функции is_int(). Она проверяет, что переменная имеет тип integer и содержит целое число.
$var = 42;
var_dump(is_int($var)); // bool(true)
Однако is_int() не подходит для строк. Например, is_int('42') вернёт false, потому что '42' - строка.
Типичная ошибка: проверять целое число из формы только с помощью is_int(). Данные из $_POST и $_GET всегда имеют тип string, поэтому is_int() всегда вернёт false. Решение: использовать filter_var() или другие методы, работающие со строками.
Цель: когда переменная гарантированно является числовым типом (например, результат математической операции).
Как проверить, что строка представляет целое число, включая знак минус?
Функция filter_var() с фильтром FILTER_VALIDATE_INT возвращает целое число, если значение является целым числом (в виде строки или int), иначе false. Можно указать диапазон.
$value = '123';
$result = filter_var($value, FILTER_VALIDATE_INT);
if ($result === false) {
echo 'Не целое число';
} else {
echo 'Целое число: ' . $result;
}
Проблема: по умолчанию filter_var не принимает числа с лидирующими нулями (например, '0123') и пробелы. Решение: использовать опцию FILTER_FLAG_ALLOW_OCTAL для восьмеричных чисел или предварительно обрезать строку функцией trim().
Цель: проверка ввода пользователя из форм, где данные приходят как строки.
Как проверить, что строка состоит только из цифр (без знака)?
ctype_digit($string) возвращает true, если все символы строки являются цифрами. Не учитывает знак минус и десятичную точку.
$str = '12345';
var_dump(ctype_digit($str)); // bool(true)
Проблема: для отрицательных чисел и пустой строки возвращает false. Решение: комбинировать с удалением знака минус через ltrim($str, '-').
Цель: проверка строк, которые должны содержать только цифры, например, номера телефонов или коды.
Как проверить, что строка является числом (в том числе с плавающей точкой), но с возможностью исключить дробные?
is_numeric($value) возвращает true для чисел и числовых строк. Для целого числа нужно дополнительно исключить дробную часть:
$str = '123';
if (is_numeric($str) && strpos($str, '.') === false && strpos($str, ',') === false) {
echo 'Целое число';
}
Проблема: is_numeric вернёт true для '1.0' или '1e2', что не является целым числом в привычном понимании. Дополнительные проверки не всегда надёжны. Решение: использовать filter_var или регулярное выражение.
Цель: когда допустимы числа в разных форматах, но нужно отсечь дробные значения.
Как проверить целое число с помощью регулярного выражения?
Шаблон /^-?\d+$/ проверяет, что строка состоит из необязательного знака минус и одной или более цифр.
$str = '-256';
if (preg_match('/^-?\d+$/', $str)) {
echo 'Целое число';
}
Проблема: не проверяет диапазон и допустимую длину числа (переполнение для больших чисел). Также может пропустить пробелы. Решение: добавить проверку длины строки или использовать фильтр с диапазоном.
Цель: тонкая настройка маски ввода, когда нужна строгая валидация формата.
Как проверить, что значение может быть безопасно преобразовано в int без потери?
Способ: привести значение к int, затем обратно к строке и сравнить с исходным.
$value = '123';
if ((string)(int)$value === (string)$value) {
echo 'Целое число';
}
Проблема: для строк с ведущими нулями ('0123' станет '123') или пробелами (' 123' станет '123') сравнение не пройдёт. Для очень больших чисел может произойти переполнение. Решение: использовать filter_var или bccomp для больших чисел.
Цель: когда нужно преобразовать строку в int, удостоверившись в целостности данных (например, перед записью в БД).
Расширенные примеры с подробными выводами и комментариями.
Дополнительные примеры
1. is_int() с различными типами
$values = [42, 3.14, '42', 'abc', true, null];
foreach ($values as $v) {
echo 'is_int(' . var_export($v, true) . ') = ' . (is_int($v) ? 'true' : 'false') . PHP_EOL;
}
is_int(42) = true
is_int(3.14) = false
is_int('42') = false
is_int('abc') = false
is_int(true) = false
is_int(null) = false
Функция is_int() работает только с типом int. Даже строка, содержащая целое число, не подходит.
2. filter_var с дополнительными опциями
$tests = ['123', '-123', '0123', ' 123', '1.5', 'abc'];
foreach ($tests as $t) {
$res = filter_var($t, FILTER_VALIDATE_INT);
echo 'filter_var(' . var_export($t, true) . ') = ' . ($res === false ? 'false' : $res) . PHP_EOL;
}
$options = ['options' => ['min_range' => 0, 'max_range' => 150]];
$age = '25';
$res = filter_var($age, FILTER_VALIDATE_INT, $options);
echo 'filter_var age 25 with range: ' . ($res === false ? 'invalid' : $res) . PHP_EOL;
filter_var('123') = 123
filter_var('-123') = -123
filter_var('0123') = false
filter_var(' 123') = false
filter_var('1.5') = false
filter_var('abc') = false
filter_var age 25 with range: 25
По умолчанию FILTER_VALIDATE_INT не принимает лидирующие нули и пробелы. Опция с диапазоном позволяет ограничить допустимые значения.
3. ctype_digit с отрицательными числами и пустой строкой
$strings = ['123', '0123', '-123', '12.3', ''];
foreach ($strings as $s) {
echo 'ctype_digit(' . var_export($s, true) . ') = ' . (ctype_digit($s) ? 'true' : 'false') . PHP_EOL;
}
$negative = '-123';
$trimmed = ltrim($negative, '-');
echo 'После удаления минуса ctype_digit(' . var_export($trimmed, true) . ') = ' . (ctype_digit($trimmed) ? 'true' : 'false') . PHP_EOL;
ctype_digit('123') = true
ctype_digit('0123') = true
ctype_digit('-123') = false
ctype_digit('12.3') = false
ctype_digit('') = false
После удаления минуса ctype_digit('123') = true
ctype_digit подходит только для строк без знака. Для отрицательных чисел нужно предварительно удалить минус.
4. Регулярное выражение с различными строками
$tests = ['256', '-256', '0', '256.0', ' 256', 'abc'];
foreach ($tests as $t) {
$match = preg_match('/^-?\d+$/', $t);
echo 'preg_match(' . var_export($t, true) . ') = ' . ($match ? 'true' : 'false') . PHP_EOL;
}
preg_match('256') = true
preg_match('-256') = true
preg_match('0') = true
preg_match('256.0') = false
preg_match(' 256') = false
preg_match('abc') = false
Регулярное выражение строго проверяет формат, но не проверяет диапазон. Пробелы не допускаются.
5. Проверка через приведение типов (string)(int)
$values = ['123', '123.45', '0123', ' -123', 'abc', '1e2'];
foreach ($values as $v) {
$isInt = (string)(int)$v === (string)$v;
echo var_export($v, true) . ' => ' . ($isInt ? 'целое' : 'не целое') . PHP_EOL;
}
'123' => целое '123.45' => не целое '0123' => не целое (ведущий ноль теряется) ' -123' => не целое (пробел) 'abc' => не целое '1e2' => не целое (научная нотация)
Метод простой, но не подходит для строк с пробелами, ведущими нулями и научной нотацией.