PHP: переменные и типы

Раздел: PHP -> Основы разработки на PHP

PHP является языком с динамической типизацией, что означает возможность автоматического преобразования типов во время выполнения. Такое поведение часто приводит к неожиданным результатам. Для повышения надёжности кода применяется строгая типизация. В этом разделе рассматриваются основные приёмы работы с переменными и типами, а также способы контроля типов.

Строгая типизация с declare(strict_types=1)

Как включить строгую типизацию в PHP?

Самый эффективный способ обеспечить контроль типов - использовать директиву declare(strict_types=1) в начале файла. Она заставляет PHP строго соблюдать объявленные типы параметров и возвращаемых значений. Если передаётся значение несоответствующего типа, возникает ошибка TypeError.

<?php
declare(strict_types=1);

function sum(int $a, int $b): int {
    return $a + $b;
}

echo sum(2, 3); // 5
echo sum(2.5, 3); // TypeError
?>

В первом вызове передаются целые числа, код выполняется успешно. Во втором - число с плавающей точкой, и PHP выбрасывает исключение, предотвращая неявное преобразование.

Как объявить функцию без строгой типизации?

Если declare(strict_types=1) отсутствует, PHP разрешает автоматическое приведение типов. Это может быть удобно при работе с внешними данными, но снижает надёжность.

<?php
function add(int $a, int $b) {
    return $a + $b;
}
echo add('5', 10); // 15, строка '5' преобразована в int
?>

Второй вариант - использовать union types (доступно с PHP 8.0). Это позволяет явно указать несколько допустимых типов.

<?php
declare(strict_types=1);
function multiply(int|float $a, int|float $b): int|float {
    return $a * $b;
}
echo multiply(2.5, 3); // 7.5
echo multiply(2, 3);   // 6
?>

Типичные ошибки и их решения:

  • Ошибка TypeError - возникает при нарушении типов в строгом режиме. Решение: проверить передаваемые значения на соответствие объявленным типам.
  • Неявное преобразование - происходит при выключенном строгом режиме. Используйте строгий режим или проверяйте типы вручную.
  • Путаница с операторами сравнения - оператор == приводит типы, а === сравнивает без приведения. Рекомендуется всегда использовать === для строгого сравнения.

Проверка и преобразование типов

Как определить тип переменной?

Основной способ - использование функций is_* (например, is_int, is_string) и gettype. Функции is_* возвращают логическое значение и безопасны для применения.

<?php
$value = 42;
if (is_int($value)) {
    echo "Целое число";
} else {
    echo "Тип: " . gettype($value);
}
?>

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

Явное преобразование выполняется с помощью операторов в скобках: (int), (float), (string) и других. Это полезно, когда необходимо гарантировать определённый тип перед операцией.

<?php
$number = "15.7";
$intNumber = (int) $number; // 15, дробная часть отбрасывается
$floatNumber = (float) $number; // 15.7
?>

Какие альтернативы проверки типов существуют?

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

<?php
$var = "123";
var_dump($var); // string(3) "123"
settype($var, "int");
echo $var; // 123
?>

Для проверки ввода пользователя лучше использовать filter_var с соответствующим флагом.

<?php
$input = "42";
if (filter_var($input, FILTER_VALIDATE_INT) !== false) {
    echo "Целое число";
} else {
    echo "Не число";
}
?>

Проблемы при работе с типами:

  • Сравнение строки и числа - при использовании == строка может быть преобразована в число, что приводит к логическим ошибкам. Решение - использовать ===.
  • Потеря данных при преобразовании - например, (int) от строки "12.5abc" даст 12, а "abc" даст 0. Решение - предварительная проверка is_numeric.
  • Неопределённые переменные - обращение к необъявленной переменной вызывает warning. Используйте isset или ?? (null coalescing operator).

Расширенные примеры работы с типами

Как использовать union types с возвратом void?

Пример
<?php
declare(strict_types=1);
function processValue(int|string $value): void {
    if (is_int($value)) {
        echo "Целое: " . $value;
    } else {
        echo "Строка: " . $value;
    }
}
processValue(42);
processValue("Hello");
?>
Целое: 42
Строка: Hello

Как преобразовать строку в число с учётом локали?

Используйте NumberFormatter из расширения intl для безопасного разбора локализованных чисел.

Пример
<?php
$locale = 'de_DE';
$formatter = new NumberFormatter($locale, NumberFormatter::DECIMAL);
$value = $formatter->parse('1.234,56');
echo $value; // 1234.56
?>
1234.56

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

Функция intval с указанием основания системы счисления позволяет преобразовывать строки в целые числа.

Пример
<?php
$hex = "1A";
$decimal = intval($hex, 16);
echo $decimal; // 26

$oct = "123";
echo intval($oct, 8); // 83, т.к. 1*64+2*8+3
?>
26
83

Как использовать match для проверки типа?

Конструкция match (PHP 8.0) может применяться для выполнения различных действий в зависимости от типа значения.

Пример
<?php
declare(strict_types=1);
function describe($value): string {
    return match (true) {
        is_int($value) => "Целое: $value",
        is_string($value) => "Строка длиной " . strlen($value),
        is_array($value) => "Массив из " . count($value) . " элементов",
        default => "Неизвестный тип"
    };
}
echo describe(100);
echo describe("PHP");
echo describe([1,2,3]);
?>
Целое: 100
Строка длиной 3
Массив из 3 элементов

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

Используйте (object) для массива и (array) для объекта. Полезно при работе с JSON.

Пример
<?php
$array = ["name" => "Alice", "age" => 30];
$object = (object) $array;
echo $object->name; // Alice

$back = (array) $object;
print_r($back);
?>
Alice
Array
(
    [name] => Alice
    [age] => 30
)

Программирование на PHP - comments

En
Php programming (php)