Жонглирование типами
PHP не требует явного определения типа при объявлении переменной.
Тип переменной определится значением, которое хранит переменная,
если тип переменной не определили.
Типом переменной $var станет string,
если переменной $var присвоили строковое значение (string).
Тип переменной изменится на int,
если позже переменной $var присвоят целочисленное значение (int).
В ряде контекстов PHP попытается автоматически преобразовать
тип значения в другой. Переменные существуют в следующих контекстах:
-
Числовой
-
Строчный
-
Логический
-
Контекст целых чисел и строк
-
Сравнительный
-
Контекст функций
Замечание:
Когда значение требуется интерпретировать как другой тип,
само значение не изменяет типы.
Как заставить PHP оценивать переменную как конкретный тип, рассказывает раздел
«Приведение типов».
Описание функции settype() объясняет, как изменить тип переменной.
Числовой контекст
Числовой контекст возникает при работе с
арифметическими операторами.
В этом контексте оба операнда интерпретируются как число с плавающей точкой (float)
и результатом станет число с плавающей точкой (float),
если один из операндов — число с плавающей точкой (float)
(или не интерпретируется как целое число (int)).
В противном случае операнды интерпретируются как целое число (int)
и результатом также станет целое число (int).
С PHP 8.0.0 выбрасывается исключение TypeError,
если не получается интерпретировать хотя бы один операнд.
Контекст целых чисел и строк
Контекст целых чисел и строк возникает при работе
с побитовыми операторами.
В этом контексте результатом станет значение string,
если каждый операнд принадлежит типу string,
иначе операнды интерпретируются как значения int
и результатом также становится тип int.
Начиная с версии 8.0.0 PHP выбрасывает ошибку TypeError,
если не получается интерпретировать хотя бы один операнд.
Контекст функций
Контекст функций возникает, когда значение передаётся типизированному параметру,
свойству или возвращается из функции, которая объявляет тип возвращаемого значения.
В контексте функции PHP проверяет, соответствует ли значение
типу параметра или возврата.
Исключение составляют два случая.
Первый: значение с типом int преобразовывается в число с плавающей точкой,
если тип объявили как float.
Второй: значение преобразовывается в принимаемое скалярное значение,
если: а) тип объявили как скалярный,
б) значение возможно преобразовать в скалярный тип
и в) активен режим нестрогой типизации,
в котором PHP работает по умолчанию.
Описание такого поведения даёт следующий параграф.
Внимание
Встроенные функции автоматически
приводят значение null к скалярным типам,
это поведение УСТАРЕЛО с PHP 8.1.0.
Неявная типизация в объявлениях простых типов
-
Объявление типа bool:
значение интерпретируется как логическое — bool.
-
Объявление типа int:
PHP интерпретирует значение как целочисленное — int,
если однозначно определит само значение, например числовую строку,
как целое число.
-
Объявление типа float:
PHP интерпретирует значение как число с плавающей точкой — float,
если однозначно определит само значение, например числовую строку,
как число с десятичной дробью.
-
Объявление типа string:
значение интерпретируется как строка — string.
Неявная типизация объединённых типов
Объявления скалярных типов
подвергаются ограниченному неявному приведению типов,
если директивой strict_types не включили
режим строгой типизации.
PHP выбирает целевой тип из следующего списка в порядке убывания приоритета,
если точный тип значения — не часть объединения:
-
int
-
float
-
string
-
bool
Интерпретатор выбирает тип, если объединение включает тип
и значение возможно привести к типу по правилам действующей
семантики проверки типов PHP.
В остальных случаях интерпретатор выбирает следующий по порядку тип.
Предостережение
Исключение: в объединении типов int и float
интерпретатор определит предпочтительный тип строкового значения действующей семантикой
числовой строки.
Например, для значения "42" PHP выберет тип int,
а для значения "42.0" — тип float.
Замечание:
Типы, которые не входят в список предпочтений, не станут целями
для неявного приведения. Говоря конкретнее, никакого неявного приведения к типам
null, false и true не выполняется.
Пример #1
Пример неявного приведения типов к типу в составе объединения
<?php
// int|string
42 --> 42 // Точное соответствие типу — выбор типа int
"42" --> "42" // Точное соответствие типу — выбор типа string
new ObjectWithToString --> "Результат работы метода __toString()"
// Объект несовместим с типом int — переход к типу string
42.0 --> 42 // Значение float совместимо с типом int — выбор типа int
42.1 --> 42 // Значение float совместимо с типом int — выбор типа int
1e100 --> "1.0E+100" // Значение float превышает диапазон типа int — переход к типу string
INF --> "INF" // Значение float превышает диапазон типа int — переход к типу string
true --> 1 // Значение bool совместимо с типом int — выбор типа int
[] --> TypeError // Массив несовместим с типами int или string — генерация ошибки
// int|float|bool
"45" --> 45 // Целочисленная числовая строка — выбор типа int
"45.0" --> 45.0 // Строка с числом с плавающей точкой — выбор типа float
"45X" --> true // Нечисловая строка — переход к типу bool
"" --> false // Нечисловая строка — переход к типу bool
"X" --> true // Нечисловая строка — переход к типу bool
[] --> TypeError // Массив несовместим с типами int, float или bool — генерация ошибки
?>
Приведение типов
Приведение типа — преобразование значения в конкретный тип.
Для преобразования типа перед значением
записывают оператор приведения типа — идентификатор типа в круглых скобках.
Пример #2 Приведение типа
<?php
$foo = 10; // Переменная $foo содержит целое число
$bar = (bool) $foo; // Переменная $bar содержит логическое значение
var_dump($bar);
?>
PHP поддерживает следующие приведения типов:
(int) — приведение типа к целому числу (int)
(bool) — приведение типа к логическому значению (bool)
(float) — приведение типа к числу с плавающей точкой (float)
(string) — приведение типа к строке (string)
(array) — приведение типа к массиву (array)
(object) — приведение типа к объекту (object)
(unset) — приведение типа к NULL
Замечание:
(integer) — псевдоним приведения типа (int).
(boolean) — псевдоним приведения типа (bool).
(binary) — псевдоним приведения типа (string).
(double) и (real) — псевдонимы приведения типа (float).
Эти приведения не используют каноническое имя типа и не рекомендуются.
Внимание
Псевдоним приведения типа (real) устарел с PHP 7.4.0,
а с PHP 8.0.0 псевдоним удалили.
Внимание
Приведение типа (unset) устарело с версии PHP 7.2.0.
Обратите внимание, что приведение (unset) равносильно
присваиванию переменной или вызову значения NULL.
Приведение (unset) удалили в PHP 8.0.0.
Предостережение
Приведение типа (binary) и префикс b
существуют для прямой поддержки.
Типы (binary) и (string)
идентичны, однако, это может измениться, не нужно на это полагаться.
Замечание:
PHP игнорирует пробелы в круглых скобках при приведении типа.
Поэтому следующие два приведения типов эквивалентны:
Вместо приведения переменной к типу string
переменную берут в двойные кавычки.
Пример #3 Механизмы приведения к строке
<?php
$foo = 10; // Переменная $foo содержит целое число
$str = "$foo"; // Переменная $str содержит строку
$fst = (string) $foo; // Переменная $fst тоже содержит строку
// Выводит: "они одинаковые"
if ($fst === $str) {
echo "они одинаковые", PHP_EOL;
}
?>
Не всегда ясно, что произойдет при приведении между конкретными типами.
Дополнительную информацию дают разделы:
Замечание:
Следующий пример справедлив для всех версий PHP,
поскольку PHP поддерживает доступ к символам строк (string)
через смещения по индексу синтаксисом, аналогичным обращению по индексу
к значениям массива (array):
Пример #4 Работа с символами строки по индексу
<?php
$a = 'car'; // Переменная $a содержит строку
$a[0] = 'b'; // Переменная $a по-прежнему содержит строку
echo $a; // Выводит: bar
?>
Дополнительную информацию даёт раздел
«
Доступ к символу в строке и его изменение
».