PHP 8.5.0 RC4 available for testing

Жонглирование типами

PHP не требует явного определения типа при объявлении переменной. Тип переменной определится значением, которое хранит переменная, если тип переменной не определили. Типом переменной $var станет string, если переменной $var присвоили строковое значение (string). Тип переменной изменится на int, если позже переменной $var присвоят целочисленное значение (int).

В ряде контекстов PHP попытается автоматически преобразовать тип значения в другой. Переменные существуют в следующих контекстах:

  • Числовой
  • Строчный
  • Логический
  • Контекст целых чисел и строк
  • Сравнительный
  • Контекст функций

Замечание: Когда значение требуется интерпретировать как другой тип, само значение не изменяет типы.

Как заставить PHP оценивать переменную как конкретный тип, рассказывает раздел «Приведение типов». Описание функции settype() объясняет, как изменить тип переменной.

Числовой контекст

Числовой контекст возникает при работе с арифметическими операторами.

В этом контексте оба операнда интерпретируются как число с плавающей точкой (float) и результатом станет число с плавающей точкой (float), если один из операндов — число с плавающей точкой (float) (или не интерпретируется как целое число (int)). В противном случае операнды интерпретируются как целое число (int) и результатом также станет целое число (int). С PHP 8.0.0 выбрасывается исключение TypeError, если не получается интерпретировать хотя бы один операнд.

Строчный контекст

Строчный контекст возникает при работе с языковыми конструкциями echo, print, при интерполяции строк или строковом операторе конкатенации.

В этом контексте значение интерпретируется как значение string. PHP выбросит ошибку TypeError, если не получится интерпретировать значение. До версии PHP 7.4.0 выдавалась ошибка уровня E_RECOVERABLE_ERROR.

Логический контекст

Логический контекст возникает при работе с условными операторами, тернарным оператором или логическими операторами.

В этом контексте значение интерпретируется как логическое — bool.

Контекст целых чисел и строк

Контекст целых чисел и строк возникает при работе с побитовыми операторами.

В этом контексте результатом станет значение string, если каждый операнд принадлежит типу string, иначе операнды интерпретируются как значения int и результатом также становится тип int. Начиная с версии 8.0.0 PHP выбрасывает ошибку TypeError, если не получается интерпретировать хотя бы один операнд.

Сравнительный контекст

Сравнительный контекст возникает при работе с операторами сравнения.

Преобразования типов, которые PHP выполняет в этом контексте, объясняет таблица сравнения типов раздела «Операторы сравнения».

Контекст функций

Контекст функций возникает, когда значение передаётся типизированному параметру, свойству или возвращается из функции, которая объявляет тип возвращаемого значения.

В контексте функции PHP проверяет, соответствует ли значение типу параметра или возврата. Исключение составляют два случая. Первый: значение с типом int преобразовывается в число с плавающей точкой, если тип объявили как float. Второй: значение преобразовывается в принимаемое скалярное значение, если: а) тип объявили как скалярный, б) значение возможно преобразовать в скалярный тип и в) активен режим нестрогой типизации, в котором PHP работает по умолчанию. Описание такого поведения даёт следующий параграф.

Внимание

Встроенные функции автоматически приводят значение null к скалярным типам, это поведение УСТАРЕЛО с PHP 8.1.0.

Неявная типизация в объявлениях простых типов

  • Объявление типа bool: значение интерпретируется как логическое — bool.
  • Объявление типа int: PHP интерпретирует значение как целочисленное — int, если однозначно определит само значение, например числовую строку, как целое число.
  • Объявление типа float: PHP интерпретирует значение как число с плавающей точкой — float, если однозначно определит само значение, например числовую строку, как число с десятичной дробью.
  • Объявление типа string: значение интерпретируется как строка — string.

Неявная типизация объединённых типов

Объявления скалярных типов подвергаются ограниченному неявному приведению типов, если директивой strict_types не включили режим строгой типизации. PHP выбирает целевой тип из следующего списка в порядке убывания приоритета, если точный тип значения — не часть объединения:

  1. int
  2. float
  3. string
  4. 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 игнорирует пробелы в круглых скобках при приведении типа. Поэтому следующие два приведения типов эквивалентны:

<?php

$foo
= (int) $bar;
$foo = ( int ) $bar;

?>

Приведение строк (string) и переменных к бинарным строкам (string):

<?php

$binary
= (binary) $string;
$binary = b"binary string";

?>

Вместо приведения переменной к типу 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

?>
Дополнительную информацию даёт раздел « Доступ к символу в строке и его изменение ».

Добавить

Примечания пользователей 6 notes

up
74
Raja
20 years ago
Uneven division of an integer variable by another integer variable will result in a float by automatic conversion -- you do not have to cast the variables to floats in order to avoid integer truncation (as you would in C, for example):

$dividend = 2;
$divisor = 3;
$quotient = $dividend/$divisor;
print $quotient; // 0.66666666666667
up
17
Anonymous
4 years ago
Cast operators have a very high precedence, for example (int)$a/$b is evaluated as ((int)$a)/$b, not as (int)($a/$b) [which would be like intdiv($a,$b) if both $a and $b are integers].
The only exceptions (as of PHP 8.0) are the exponentiation operator ** [i.e. (int)$a**$b is evaluated as (int)($a**$b) rather than ((int)$a)**$b] and the special access/invocation operators ->, ::, [] and () [i.e. in each of (int)$a->$b, (int)$a::$b, (int)$a[$b] and (int)$a($b), the cast is performed last on the result of the variable expression].
up
2
Anonymous
1 year ago
Type casting in expressions is executed first.
The casting is assigned to the value, not to the expression result.
Examples:

<?php

$string
= "777";

var_dump( $string === 777 ); // FALSE
var_dump( (int) $string === 777 ); // TRUE
var_dump( ( (int) $string ) === 777 ); // TRUE
var_dump( (int) ( $string === 777 ) ); // 0
?>
up
26
fardelian
12 years ago
Casting objects to arrays is a pain. Example:

<?php

class MyClass {

private
$priv = 'priv_value';
protected
$prot = 'prot_value';
public
$pub = 'pub_value';
public
$MyClasspriv = 'second_pub_value';

}

$test = new MyClass();
echo
'<pre>';
print_r((array) $test);

/*
Array
(
[MyClasspriv] => priv_value
[*prot] => prot_value
[pub] => pub_value
[MyClasspriv] => second_pub_value
)
*/

?>

Yes, that looks like an array with two keys with the same name and it looks like the protected field was prepended with an asterisk. But that's not true:

<?php

foreach ((array) $test as $key => $value) {
$len = strlen($key);
echo
"{$key} ({$len}) => {$value}<br />";
for (
$i = 0; $i < $len; ++$i) {
echo
ord($key[$i]) . ' ';
}
echo
'<hr />';
}

/*
MyClasspriv (13) => priv_value
0 77 121 67 108 97 115 115 0 112 114 105 118
*prot (7) => prot_value
0 42 0 112 114 111 116
pub (3) => pub_value
112 117 98
MyClasspriv (11) => second_pub_value
77 121 67 108 97 115 115 112 114 105 118
*/

?>

The char codes show that the protected keys are prepended with '\0*\0' and private keys are prepended with '\0'.__CLASS__.'\0' so be careful when playing around with this.
up
14
miracle at 1oo-percent dot de
19 years ago
If you want to convert a string automatically to float or integer (e.g. "0.234" to float and "123" to int), simply add 0 to the string - PHP will do the rest.

e.g.

$val = 0 + "1.234";
(type of $val is float now)

$val = 0 + "123";
(type of $val is integer now)
up
19
Anonymous
23 years ago
Printing or echoing a FALSE boolean value or a NULL value results in an empty string:
(string)TRUE //returns "1"
(string)FALSE //returns ""
echo TRUE; //prints "1"
echo FALSE; //prints nothing!
To Top