mirror of
https://github.com/php/doc-ru.git
synced 2026-03-23 23:32:16 +01:00
509 lines
23 KiB
XML
509 lines
23 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
||
<!-- EN-Revision: 78a11d3ca004ee937549d932e77a79c51b9777cd Maintainer: shein Status: ready -->
|
||
<!-- Reviewed: no -->
|
||
<sect1 xml:id="language.types.type-juggling">
|
||
<title>Жонглирование типами</title>
|
||
|
||
<simpara>
|
||
PHP не требует явного определения типа при объявлении переменной.
|
||
Тип переменной определится значением, которое хранит переменная,
|
||
если тип переменной не определили.
|
||
Типом переменной <varname>$var</varname> станет <type>string</type>,
|
||
если переменной <varname>$var</varname> присвоили строковое значение (<type>string</type>).
|
||
Тип переменной изменится на <type>int</type>,
|
||
если позже переменной <varname>$var</varname> присвоят целочисленное значение (<type>int</type>).
|
||
</simpara>
|
||
|
||
<para>
|
||
В ряде контекстов PHP попытается автоматически преобразовать
|
||
тип значения в другой. Переменные существуют в следующих контекстах:
|
||
<itemizedlist>
|
||
<listitem>
|
||
<simpara>Числовой</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>Строчный</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>Логический</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>Контекст целых чисел и строк</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>Сравнительный</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>Контекст функций</simpara>
|
||
</listitem>
|
||
</itemizedlist>
|
||
</para>
|
||
|
||
<note>
|
||
<simpara>
|
||
Когда значение требуется интерпретировать как другой тип,
|
||
само значение <emphasis>не</emphasis> изменяет типы.
|
||
</simpara>
|
||
</note>
|
||
|
||
<simpara>
|
||
Как заставить PHP оценивать переменную как конкретный тип, рассказывает раздел
|
||
«<link linkend="language.types.typecasting">Приведение типов</link>».
|
||
Описание функции <function>settype</function> объясняет, как изменить тип переменной.
|
||
</simpara>
|
||
|
||
<sect2>
|
||
<title>Числовой контекст</title>
|
||
|
||
<simpara>
|
||
Числовой контекст возникает при работе с
|
||
<link linkend="language.operators.arithmetic">арифметическими операторами</link>.
|
||
</simpara>
|
||
|
||
<simpara>
|
||
В этом контексте оба операнда интерпретируются как число с плавающей точкой (<type>float</type>)
|
||
и результатом станет число с плавающей точкой (<type>float</type>),
|
||
если один из операндов — число с плавающей точкой (<type>float</type>)
|
||
(или не интерпретируется как целое число (<type>int</type>)).
|
||
В противном случае операнды интерпретируются как целое число (<type>int</type>)
|
||
и результатом также станет целое число (<type>int</type>).
|
||
С PHP 8.0.0 выбрасывается исключение <classname>TypeError</classname>,
|
||
если не получается интерпретировать хотя бы один операнд.
|
||
</simpara>
|
||
</sect2>
|
||
|
||
<sect2>
|
||
<title>Строчный контекст</title>
|
||
|
||
<simpara>
|
||
Строчный контекст возникает при работе с языковыми конструкциями <function>echo</function>,
|
||
<function>print</function>, при <link linkend="language.types.string.parsing">интерполяции строк</link>
|
||
или строковом <link linkend="language.operators.string">операторе конкатенации</link>.
|
||
</simpara>
|
||
|
||
<simpara>
|
||
В этом контексте значение интерпретируется как значение <type>string</type>.
|
||
PHP выбросит ошибку <classname>TypeError</classname>,
|
||
если не получится интерпретировать значение.
|
||
До версии PHP 7.4.0 выдавалась ошибка уровня <constant>E_RECOVERABLE_ERROR</constant>.
|
||
</simpara>
|
||
</sect2>
|
||
|
||
<sect2>
|
||
<title>Логический контекст</title>
|
||
|
||
<simpara>
|
||
Логический контекст возникает при работе с условными операторами,
|
||
<link linkend="language.operators.comparison.ternary">тернарным оператором</link>
|
||
или <link linkend="language.operators.logical">логическими операторами</link>.
|
||
</simpara>
|
||
|
||
<simpara>
|
||
В этом контексте значение интерпретируется как логическое — <type>bool</type>.
|
||
</simpara>
|
||
</sect2>
|
||
|
||
<sect2>
|
||
<title>Контекст целых чисел и строк</title>
|
||
|
||
<simpara>
|
||
Контекст целых чисел и строк возникает при работе
|
||
<link linkend="language.operators.bitwise">с побитовыми операторами</link>.
|
||
</simpara>
|
||
|
||
<simpara>
|
||
В этом контексте результатом станет значение <type>string</type>,
|
||
если каждый операнд принадлежит типу <type>string</type>,
|
||
иначе операнды интерпретируются как значения <type>int</type>
|
||
и результатом также становится тип <type>int</type>.
|
||
Начиная с версии 8.0.0 PHP выбрасывает ошибку <classname>TypeError</classname>,
|
||
если не получается интерпретировать хотя бы один операнд.
|
||
</simpara>
|
||
</sect2>
|
||
|
||
<sect2>
|
||
<title>Сравнительный контекст</title>
|
||
|
||
<simpara>
|
||
Сравнительный контекст возникает при работе
|
||
<link linkend="language.operators.comparison">с операторами сравнения</link>.
|
||
</simpara>
|
||
|
||
<simpara>
|
||
Преобразования типов, которые PHP выполняет в этом контексте, объясняет
|
||
<link linkend="language.operators.comparison.types">таблица сравнения типов</link>
|
||
раздела «Операторы сравнения».
|
||
</simpara>
|
||
</sect2>
|
||
|
||
<sect2 xml:id="language.types.type-juggling.function">
|
||
<title>Контекст функций</title>
|
||
|
||
<simpara>
|
||
Контекст функций возникает, когда значение передаётся типизированному параметру,
|
||
свойству или возвращается из функции, которая объявляет тип возвращаемого значения.
|
||
</simpara>
|
||
|
||
<para>
|
||
В контексте функции PHP проверяет, соответствует ли значение
|
||
типу параметра или возврата.
|
||
Исключение составляют два случая.
|
||
Первый: значение с типом <type>int</type> преобразовывается в число с плавающей точкой,
|
||
если тип объявили как <type>float</type>.
|
||
|
||
Второй: значение преобразовывается в принимаемое скалярное значение,
|
||
если: а) тип объявили как <emphasis>скалярный</emphasis>,
|
||
б) значение возможно преобразовать в скалярный тип
|
||
и в) активен режим нестрогой типизации,
|
||
в котором PHP работает по умолчанию.
|
||
Описание такого поведения даёт следующий параграф.
|
||
</para>
|
||
|
||
<warning>
|
||
<simpara>
|
||
<link linkend="functions.internal">Встроенные функции</link> автоматически
|
||
приводят значение &null; к скалярным типам,
|
||
это поведение <emphasis>УСТАРЕЛО</emphasis> с PHP 8.1.0.
|
||
</simpara>
|
||
</warning>
|
||
|
||
<sect3 xml:id="language.types.type-juggling.function.simple">
|
||
<title>
|
||
Неявная типизация в объявлениях простых типов
|
||
</title>
|
||
<itemizedlist>
|
||
<listitem>
|
||
<simpara>
|
||
Объявление типа <type>bool</type>:
|
||
значение интерпретируется как логическое — <type>bool</type>.
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
Объявление типа <type>int</type>:
|
||
PHP интерпретирует значение как целочисленное — <type>int</type>,
|
||
если однозначно определит само значение, например <link linkend="language.types.numeric-strings">числовую строку</link>,
|
||
как целое число.
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
Объявление типа <type>float</type>:
|
||
PHP интерпретирует значение как число с плавающей точкой — <type>float</type>,
|
||
если однозначно определит само значение, например <link linkend="language.types.numeric-strings">числовую строку</link>,
|
||
как число с десятичной дробью.
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
Объявление типа <type>string</type>:
|
||
значение интерпретируется как строка — <type>string</type>.
|
||
</simpara>
|
||
</listitem>
|
||
</itemizedlist>
|
||
</sect3>
|
||
|
||
<sect3 xml:id="language.types.type-juggling.function.union">
|
||
<title>
|
||
Неявная типизация объединённых типов
|
||
</title>
|
||
<para>
|
||
Объявления скалярных типов
|
||
подвергаются ограниченному неявному приведению типов,
|
||
если директивой <literal>strict_types</literal> не включили
|
||
режим строгой типизации.
|
||
PHP выбирает целевой тип из следующего списка в порядке убывания приоритета,
|
||
если точный тип значения — не часть объединения:
|
||
|
||
<orderedlist>
|
||
<listitem>
|
||
<simpara>
|
||
<type>int</type>
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
<type>float</type>
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
<type>string</type>
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
<type>bool</type>
|
||
</simpara>
|
||
</listitem>
|
||
</orderedlist>
|
||
|
||
Интерпретатор выбирает тип, если объединение включает тип
|
||
и значение возможно привести к типу по правилам действующей
|
||
семантики проверки типов PHP.
|
||
В остальных случаях интерпретатор выбирает следующий по порядку тип.
|
||
</para>
|
||
|
||
<caution>
|
||
<para>
|
||
Исключение: в объединении типов int и float
|
||
интерпретатор определит предпочтительный тип строкового значения действующей семантикой
|
||
<link linkend="language.types.numeric-strings">числовой строки</link>.
|
||
Например, для значения <literal>"42"</literal> PHP выберет тип <type>int</type>,
|
||
а для значения <literal>"42.0"</literal> — тип <type>float</type>.
|
||
</para>
|
||
</caution>
|
||
|
||
<note>
|
||
<para>
|
||
Типы, которые не входят в список предпочтений, не станут целями
|
||
для неявного приведения. Говоря конкретнее, никакого неявного приведения к типам
|
||
<type>null</type>, <type>false</type> и <type>true</type> не выполняется.
|
||
</para>
|
||
</note>
|
||
|
||
<example>
|
||
<title>
|
||
Пример неявного приведения типов к типу в составе объединения
|
||
</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?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 — генерация ошибки
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</sect3>
|
||
|
||
</sect2>
|
||
|
||
<sect2 xml:id="language.types.typecasting">
|
||
<title>Приведение типов</title>
|
||
|
||
<simpara>
|
||
Приведение типа — преобразование значения в конкретный тип.
|
||
Для преобразования типа перед значением
|
||
записывают оператор приведения типа — идентификатор типа в круглых скобках.
|
||
</simpara>
|
||
|
||
<example>
|
||
<title>Приведение типа</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
$foo = 10; // Переменная $foo содержит целое число
|
||
$bar = (bool) $foo; // Переменная $bar содержит логическое значение
|
||
|
||
var_dump($bar);
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
|
||
<simpara>
|
||
PHP поддерживает следующие приведения типов:
|
||
</simpara>
|
||
|
||
|
||
<simplelist>
|
||
<member><literal>(int)</literal> — приведение типа к целому числу (<type>int</type>)</member>
|
||
<member><literal>(bool)</literal> — приведение типа к логическому значению (<type>bool</type>)</member>
|
||
<member><literal>(float)</literal> — приведение типа к числу с плавающей точкой (<type>float</type>)</member>
|
||
<member><literal>(string)</literal> — приведение типа к строке (<type>string</type>)</member>
|
||
<member><literal>(array)</literal> — приведение типа к массиву (<type>array</type>)</member>
|
||
<member><literal>(object)</literal> — приведение типа к объекту (<type>object</type>)</member>
|
||
<member><literal>(unset)</literal> — приведение типа к <type>NULL</type></member>
|
||
</simplelist>
|
||
|
||
<warning>
|
||
<para>
|
||
<literal>(integer)</literal> — псевдоним приведения типа <literal>(int)</literal>.
|
||
<literal>(boolean)</literal> — псевдоним приведения типа <literal>(bool)</literal>.
|
||
<literal>(binary)</literal> — псевдоним приведения типа <literal>(string)</literal>.
|
||
<literal>(double)</literal> и <literal>(real)</literal> — псевдонимы приведения типа <literal>(float)</literal>.
|
||
Эти приведения не используют каноническое имя типа и являются устаревшими начиная с PHP 8.5.0.
|
||
</para>
|
||
</warning>
|
||
|
||
<warning>
|
||
<simpara>
|
||
Псевдоним приведения типа <literal>(real)</literal> устарел с PHP 7.4.0,
|
||
а с PHP 8.0.0 псевдоним удалили.
|
||
</simpara>
|
||
</warning>
|
||
|
||
<warning>
|
||
<simpara>
|
||
Приведение типа <literal>(unset)</literal> устарело с версии PHP 7.2.0.
|
||
Обратите внимание, что приведение <literal>(unset)</literal> равносильно
|
||
присваиванию переменной или вызову значения <type>NULL</type>.
|
||
Приведение <literal>(unset)</literal> удалили в PHP 8.0.0.
|
||
</simpara>
|
||
</warning>
|
||
|
||
<caution>
|
||
<simpara>
|
||
Приведение типа <literal>(binary)</literal> и префикс <literal>b</literal>
|
||
существуют для прямой поддержки.
|
||
Типы <literal>(binary)</literal> и <literal>(string)</literal>
|
||
идентичны, однако, это может измениться, не нужно на это полагаться.
|
||
</simpara>
|
||
</caution>
|
||
|
||
<note>
|
||
<para>
|
||
PHP игнорирует пробелы в круглых скобках при приведении типа.
|
||
Поэтому следующие два приведения типов эквивалентны:
|
||
<informalexample>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
$foo = (int) $bar;
|
||
$foo = ( int ) $bar;
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
</para>
|
||
</note>
|
||
|
||
<informalexample>
|
||
<simpara>
|
||
Приведение строк (<type>string</type>) и переменных
|
||
к бинарным строкам (<type>string</type>):
|
||
</simpara>
|
||
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
$binary = (binary) $string;
|
||
$binary = b"binary string";
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
|
||
<simpara>
|
||
Вместо приведения переменной к типу <type>string</type>
|
||
переменную берут в двойные кавычки.
|
||
</simpara>
|
||
|
||
<example>
|
||
<title>Механизмы приведения к строке</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
$foo = 10; // Переменная $foo содержит целое число
|
||
$str = "$foo"; // Переменная $str содержит строку
|
||
$fst = (string) $foo; // Переменная $fst тоже содержит строку
|
||
|
||
// Выводит: "они одинаковые"
|
||
if ($fst === $str) {
|
||
echo "они одинаковые", PHP_EOL;
|
||
}
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
|
||
<para>
|
||
Не всегда ясно, что произойдет при приведении между конкретными типами.
|
||
Дополнительную информацию дают разделы:
|
||
|
||
<simplelist>
|
||
<member><link linkend="language.types.boolean.casting">Преобразование типа к логическому значению (boolean)</link></member>
|
||
<member><link linkend="language.types.integer.casting">Преобразование типа к целому числу (integer)</link></member>
|
||
<member><link linkend="language.types.float.casting">Преобразование типа к числу с плавающей точкой (float)</link></member>
|
||
<member><link linkend="language.types.string.casting">Преобразование типа к строке (string)</link></member>
|
||
<member><link linkend="language.types.array.casting">Преобразование типа к массиву (array)</link></member>
|
||
<member><link linkend="language.types.object.casting">Преобразование типа к объекту (object)</link></member>
|
||
<member><link linkend="language.types.resource.casting">Преобразование типа к ресурсу (resource)</link></member>
|
||
<member><link linkend="language.types.null.casting">Преобразование типа к NULL</link></member>
|
||
<member><link linkend="types.comparisons">Таблицы сравнения типов</link></member>
|
||
</simplelist>
|
||
</para>
|
||
|
||
<note>
|
||
<simpara>
|
||
Следующий пример справедлив для всех версий PHP,
|
||
поскольку PHP поддерживает доступ к символам строк (<type>string</type>)
|
||
через смещения по индексу синтаксисом, аналогичным обращению по индексу
|
||
к значениям массива (<type>array</type>):
|
||
</simpara>
|
||
|
||
<example>
|
||
<title>Работа с символами строки по индексу</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
$a = 'car'; // Переменная $a содержит строку
|
||
$a[0] = 'b'; // Переменная $a по-прежнему содержит строку
|
||
echo $a; // Выводит: bar
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
|
||
<simpara>
|
||
Дополнительную информацию даёт раздел
|
||
«<link linkend="language.types.string.substr">
|
||
Доступ к символу в строке и его изменение
|
||
</link>».
|
||
</simpara>
|
||
</note>
|
||
</sect2>
|
||
|
||
</sect1>
|
||
<!-- Keep this comment at the end of the file
|
||
Local variables:
|
||
mode: sgml
|
||
sgml-omittag:t
|
||
sgml-shorttag:t
|
||
sgml-minimize-attributes:nil
|
||
sgml-always-quote-attributes:t
|
||
sgml-indent-step:1
|
||
sgml-indent-data:t
|
||
indent-tabs-mode:nil
|
||
sgml-parent-document:nil
|
||
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
|
||
sgml-exposed-tags:nil
|
||
sgml-local-catalogs:nil
|
||
sgml-local-ecat-files:nil
|
||
End:
|
||
vim600: syn=xml fen fdm=syntax fdl=2 si
|
||
vim: et tw=78 syn=sgml
|
||
vi: ts=1 sw=1
|
||
-->
|