Определение типа и содержания переменных в PHP

Раздел: Стандартные функции -> Проверка типов

Основные функции проверки типов и символов

Наиболее эффективным речением для проверки типа переменной и содержимого строки является комбинация встроенных функций семейства is_* и ctype_*. Первые определяют базовый тип данных (целое число, строка, массив и т.д.), вторые анализируют состав строки (только цифры, только буквы, алфавитно-цифровые символы).


$number = 123;
$string = '456';

if (is_int($number)) {
    echo "Переменная \$number является целым числом";
}
if (ctype_digit($string)) {
    echo "Строка \$string состоит только из цифр";
}

Php проверка символов (проверка символов и типов в php)

Переменная $number является целым числом
Строка $string состоит только из цифр
Проблема в том, что is_int вернет false для строки, содержащей цифры, а ctype_digit принимает только строки. Для чисел с плавающей точкой используется is_float, для строк - is_string. Комбинирование функций позволяет точно определить тип и содержимое. Например, если нужно проверить, что значение является целым числом или строкой из цифр, придется использовать несколько условий.

Как проверить целое число с ограничением диапазона?

Функция filter_var с фильтром FILTER_VALIDATE_INT позволяет не только убедиться, что значение является целым числом, но и задать минимальное и максимальное значение.


$input = '150';
$options = [
    'options' => [
        'min_range' => 100,
        'max_range' => 200
    ]
];
if (filter_var($input, FILTER_VALIDATE_INT, $options) !== false) {
    echo "Целое число в диапазоне от 100 до 200";
} else {
    echo "Не подходит";
}
Целое число в диапазоне от 100 до 200
Фильтр возвращает само число при успехе или false. Из-за того что ноль тоже может быть валидным значением, необходимо использовать строгое сравнение !== false. Фильтр также работает с числами в строковом представлении, но не изменяет исходный тип.

Как точно определить тип переменной без приведения?

Функция gettype возвращает строковое обозначение типа, позволяя сравнить его с нужным значением.


$var = [1, 2, 3];
if (gettype($var) === 'array') {
    echo "Это массив";
}
Это массив
gettype не различает подтипы, например, не отличит int от float, если переменная является числом с плавающей точкой. Также результат может быть 'unknown type' для неподдерживаемых типов. Для логических значений возвращается 'boolean', а не 'bool'.

Как быстро увидеть тип и значение при отладке?

var_dump выводит всю информацию о переменной, включая тип и значение. Это удобно для разработки, но не для условных операторов.


$data = 12.34;
var_dump($data);
float(12.34)
var_dump не возвращает результат, а сразу выводит в stdout. Для логирования следует использовать error_log или записи в файл. Также var_dump может вывести много данных для больших массивов.

Как отличить null от false или пустой строки?

С помощью is_null и is_bool можно однозначно определить, является ли переменная null или булевым значением. empty не подходит, так как пустая строка, 0, '0', null, false, [] считаются пустыми.


$value1 = null;
$value2 = false;
if (is_null($value1)) {
    echo "Первая переменная равна null";
}
if (is_bool($value2)) {
    echo "Вторая переменная булева";
}
Первая переменная равна null
Вторая переменная булева
is_null вернет true только для null, а is_bool для true и false. Не путать с is_numeric, который вернет true для числовых строк, но не для null.

Как убедиться, что объект принадлежит определённому классу или реализует интерфейс?

Оператор instanceof и функция is_a проверяют принадлежность объекта классу или интерфейсу, включая наследование.


class Animal {}
class Dog extends Animal {}

$pet = new Dog();
if ($pet instanceof Animal) {
    echo "Собака является животным";
}
if (is_a($pet, 'Dog')) {
    echo "Объект является собакой";
}
Собака является животным
Объект является собакой
instanceof требует объект слева, а is_a принимает объект или строку с именем класса. Для проверки на реализацию интерфейса также используется instanceof. Не работает с примитивными типами.

Как проверить, что переменная является открытым ресурсом (например, файловым дескриптором)?

Функция is_resource возвращает true, если переменная содержит ресурс. После закрытия ресурса она вернёт false.


$fp = fopen('/tmp/test.txt', 'w');
if (is_resource($fp)) {
    fwrite($fp, 'Hello');
    fclose($fp);
} else {
    echo "Не удалось открыть файл";
}
(файл успешно записан)
Ресурсы в PHP устаревают, многие функции теперь возвращают объекты. is_resource может не распознать объектный ресурс (например, из PDO). Для новых расширений рекомендуется проверять наличие объекта и его методов.

Как проверить, что строка соответствует сложному шаблону (только латиница, цифры и подчёркивание)?

Регулярные выражения с preg_match дают полный контроль над содержимым строки.


$username = 'user_123';
if (preg_match('/^[a-zA-Z0-9_]+$/', $username)) {
    echo "Имя пользователя корректно";
} else {
    echo "Недопустимые символы";
}
Имя пользователя корректно
Регулярные выражения требуют осторожности с юникодом (использовать модификатор u). При больших строках производительность может снизиться. Для простых проверок лучше подходят ctype_*.

Как быстро проверить, что строка состоит из букв и цифр (без специальных символов)?

Функция ctype_alnum делает это за одну операцию, но только для строк в кодировке ASCII.


$string = 'Hello123';
if (ctype_alnum($string)) {
    echo "Строка содержит только буквы и цифры";
}
Строка содержит только буквы и цифры
ctype_alnum не поддерживает кириллицу и другие многобайтовые кодировки. Для utf-8 необходимо использовать регулярные выражения с модификатором u или mb_ereg.

Как проверить, что переменная является массивом и не пуста?

Комбинация is_array для проверки типа и empty для проверки на пустоту.


$arr = [1, 2];
if (is_array($arr) && !empty($arr)) {
    echo "Массив не пустой";
}
Массив не пустой
empty считает массив пустым, если в нём нет элементов. Для проверки существования ключа лучше использовать array_key_exists или isset. is_array не отличает обычные массивы от объектов ArrayObject.

Как проверить, что переменная может быть вызвана как функция (callback)?

is_callable проверяет, существует ли функция или метод, и может ли он быть вызван.


function myFunction() { return 'OK'; }
$callback = 'myFunction';
if (is_callable($callback)) {
    echo $callback();
}
OK
is_callable для методов класса требует указать объект или имя класса и метод в виде массива. Не проверяет количество и типы аргументов. Для проверки существования функции без вызова используйте function_exists.

Расширенные примеры проверки типов и символов

Пример 1: Комплексная валидация формы

Проверка имени (только буквы латиницы или кириллицы с помощью регулярного выражения с u-модификатором), возраста (целое от 18 до 100) и email.

Пример

$name = 'Алексей';
$age = '30';
$email = 'alex@example.com';

// Проверка имени: буквы, пробелы, дефисы (utf-8)
if (preg_match('/^[\p{L}\s-]+$/u', $name)) {
    echo "Имя корректно";
} else {
    echo "Имя содержит недопустимые символы";
}

// Проверка возраста
$ageOptions = ['options' => ['min_range' => 18, 'max_range' => 100]];
$ageValid = filter_var($age, FILTER_VALIDATE_INT, $ageOptions);
if ($ageValid !== false) {
    echo "Возраст {$ageValid} подходит";
} else {
    echo "Возраст вне диапазона";
}

// Проверка email
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
    echo "Email корректен";
} else {
    echo "Email не корректен";
}
Имя корректно
Возраст 30 подходит
Email корректен

Проблемы: регулярное выражение с \p{L} может быть медленным на длинных строках, а filter_var для email не проверяет существование домена.

Пример 2: Проверка callback перед вызовом

Использование is_callable для безопасного вызова функции, переданной в качестве параметра.

Пример

function processData($data, $callback) {
    if (!is_callable($callback)) {
        throw new InvalidArgumentException('Callback не является вызываемым');
    }
    return call_user_func($callback, $data);
}

try {
    $result = processData([1, 2, 3], 'array_sum');
    echo $result; // 6
} catch (Exception $e) {
    echo $e->getMessage();
}
6

Важно: is_callable для метода объекта нужно передавать массив: [$obj, 'methodName'] или ['ClassName', 'staticMethod'].

Пример 3: Использование утверждений (assert) для отладки типов

Утверждения помогают проверять типы на этапе разработки, но не должны использоваться в production без осторожности.

Пример

function divide(int $a, int $b): float {
    assert($b !== 0, 'Деление на ноль');
    return $a / $b;
}

echo divide(10, 2); // 5
5

По умолчанию assert ничего не делает в production. Для включения используйте assert_options(ASSERT_ACTIVE, 1);

Пример 4: Проверка типа с помощью is_a и интерфейсов

Проверка, реализует ли объект определённый интерфейс, без привязки к конкретному классу.

Пример

interface Loggable {
    public function getLog(): string;
}
class User implements Loggable {
    public function getLog(): string {
        return 'User log';
    }
}

$user = new User();
if (is_a($user, 'Loggable')) {
    echo "Объект реализует Loggable";
}
Объект реализует Loggable

is_a принимает строку имени класса или интерфейса, а также может работать с третьим аргументом для проверки, является ли объект экземпляром или реализует интерфейс.

Пример 5: Проверка строк на наличие только печатных символов

Функция ctype_print определяет, состоит ли строка исключительно из видимых (печатных) символов, исключая управляющие коды.

Пример

$string = "Hello World!";
if (ctype_print($string)) {
    echo "Строка содержит только печатные символы";
} else {
    echo "Есть управляющие символы";
}
$string2 = "Hello\nWorld";
if (ctype_print($string2)) {
    echo "Вторая строка печатна";
} else {
    echo "Вторая строка содержит символ новой строки";
}
Строка содержит только печатные символы
Вторая строка содержит символ новой строки

Проблема: ctype_print не различает пробелы (они считаются печатными), но символы табуляции, новой строки и возврата каретки не проходят.

Пример 6: Безопасное приведение типов с settype и проверкой

settype изменяет тип переменной на указанный, возвращая true при успехе. Можно комбинировать с is_* для подтверждения.

Пример

$value = '42.5';
if (settype($value, 'int')) {
    // $value теперь 42
    echo "После приведения к int: $value";
} else {
    echo "Не удалось привести к int";
}
После приведения к int: 42

Проблема: settype модифицирует исходную переменную, что может быть неожиданно. Лучше использовать приведение (int) $value, но без проверки. settype также теряет дробную часть при приведении к int.

Проверка символов и типов в PHP - comments

En
Php проверка символов (php)