mirror of
https://github.com/sigmasternchen/php-doc-en
synced 2025-03-15 08:28:54 +00:00
Rewrite type juggling page (#1542)
Describe all the different ways and contexts in which PHP can type juggle. The only bit which is not described is how ``++`` and ``--`` behave as they have peculiar behaviour which is documented on the operator page already.
This commit is contained in:
parent
38f5bb6cc0
commit
8de1190205
1 changed files with 266 additions and 184 deletions
|
@ -1,65 +1,47 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- $Revision$ -->
|
||||
<sect1 xml:id="language.types.type-juggling">
|
||||
<title>Type Juggling</title>
|
||||
|
||||
<simpara>
|
||||
PHP does not require (or support) explicit type definition in variable
|
||||
declaration; a variable's type is determined by the context in which the
|
||||
variable is used. That is to say, if a <type>string</type> value is assigned
|
||||
to variable <varname>$var</varname>, <varname>$var</varname> becomes a
|
||||
<type>string</type>. If an <type>int</type> value is then assigned to
|
||||
<varname>$var</varname>, it becomes an <type>int</type>.
|
||||
PHP does not require explicit type definition in variable declaration.
|
||||
In this case, the type of a variable is determined by the value it stores.
|
||||
That is to say, if a <type>string</type> is assigned to variable
|
||||
<varname>$var</varname>, then <varname>$var</varname> is of type
|
||||
<type>string</type>. If afterwards an <type>int</type> value is assigned
|
||||
to <varname>$var</varname>, it will be of type <type>int</type>.
|
||||
</simpara>
|
||||
|
||||
<para>
|
||||
An example of PHP's automatic type conversion is the multiplication operator '*'.
|
||||
If either operand is a <type>float</type>, then both operands are evaluated as
|
||||
<type>float</type>s, and the result will be a <type>float</type>. Otherwise,
|
||||
the operands will be interpreted as <type>int</type>s, and the result will
|
||||
also be an <type>int</type>. Note that this does <emphasis>not</emphasis>
|
||||
change the types of the operands themselves; the only change is in how the
|
||||
operands are evaluated and what the type of the expression itself is.
|
||||
PHP may attempt to convert the type of a value to another automatically
|
||||
in certain contexts. The different contexts which exist are:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<simpara>Numeric</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>String</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>Logical</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>Integral and string</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>Comparative</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>Function</simpara>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
$foo = "1"; // $foo is string (ASCII 49)
|
||||
$foo *= 2; // $foo is now an integer (2)
|
||||
$foo = $foo * 1.3; // $foo is now a float (2.6)
|
||||
$foo = 5 * "10 Little Piggies"; // $foo is integer (50)
|
||||
$foo = 5 * "10 Small Pigs"; // $foo is integer (50)
|
||||
?>
|
||||
]]>
|
||||
<!-- bad example, no real operator (must be used with variable, modifies it too)
|
||||
$foo++; // $foo is the string "2" (ASCII 50)
|
||||
|
||||
TODO: explain ++/- - behaviour with strings
|
||||
|
||||
examples:
|
||||
|
||||
++'001' = '002'
|
||||
++'abc' = 'abd'
|
||||
++'xyz' = 'xza'
|
||||
++'9.9' = '9.0'
|
||||
++'-3' = '-4'
|
||||
- -'9' = 8 (integer!)
|
||||
- -'5.5' = '5.5'
|
||||
- -'-9' = -10 (integer)
|
||||
- -'09' = 8 (integer)
|
||||
- -'abc' = 'abc'
|
||||
|
||||
-->
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
|
||||
<simpara>
|
||||
If the last two examples above seem odd, see how
|
||||
<link linkend="language.types.numeric-strings">numeric strings</link>
|
||||
convert to integers.
|
||||
</simpara>
|
||||
<note>
|
||||
<simpara>
|
||||
When a value needs to be interpreted as a different type, the value itself
|
||||
does <emphasis>not</emphasis> change types.
|
||||
</simpara>
|
||||
</note>
|
||||
|
||||
<simpara>
|
||||
To force a variable to be evaluated as a certain type, see the section on
|
||||
|
@ -67,119 +49,222 @@ examples:
|
|||
type of a variable, see the <function>settype</function> function.
|
||||
</simpara>
|
||||
|
||||
<para>
|
||||
To test any of the examples in this section, use the
|
||||
<function>var_dump</function> function.
|
||||
</para>
|
||||
<sect2>
|
||||
<title>Numeric contexts</title>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
The behaviour of an automatic conversion to <type>array</type> is currently
|
||||
undefined.
|
||||
</para>
|
||||
<simpara>
|
||||
This is the context when using an
|
||||
<link linkend="language.operators.arithmetic">arithmetical operator</link>.
|
||||
</simpara>
|
||||
|
||||
<simpara>
|
||||
In this context if either operand is a <type>float</type> (or not
|
||||
interpretable as an <type>int</type>), both operands are interpreted as
|
||||
<type>float</type>s, and the result will be a <type>float</type>.
|
||||
Otherwise, the operands will be interpreted as <type>int</type>s,
|
||||
and the result will also be an <type>int</type>.
|
||||
As of PHP 8.0.0, if one of the operands cannot be interpreted a
|
||||
<classname>TypeError</classname> is thrown.
|
||||
</simpara>
|
||||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>String contexts</title>
|
||||
|
||||
<simpara>
|
||||
This is the context when using <function>echo</function>,
|
||||
<function>print</function>, string interpolation, or the string
|
||||
<link linkend="language.operators.string">concatenation operator</link>.
|
||||
</simpara>
|
||||
|
||||
<simpara>
|
||||
In this context the value will be interpreted as <type>string</type>.
|
||||
</simpara>
|
||||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>Logical contexts</title>
|
||||
|
||||
<simpara>
|
||||
This is the context when using conditional statements, the
|
||||
<link linkend="language.operators.comparison.ternary">ternary operator</link>,
|
||||
or a <link linkend="language.operators.logical">logical operator</link>.
|
||||
</simpara>
|
||||
|
||||
<simpara>
|
||||
In this context the value will be interpreted as <type>bool</type>.
|
||||
</simpara>
|
||||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>Integral and string contexts</title>
|
||||
|
||||
<simpara>
|
||||
This is the context when using a
|
||||
<link linkend="language.operators.bitwise">bitwise operators</link>.
|
||||
</simpara>
|
||||
|
||||
<simpara>
|
||||
In this context if all operands are of type <type>string</type> the result
|
||||
will also be a <type>string</type>.
|
||||
Otherwise, the operands will be interpreted as <type>int</type>s,
|
||||
and the result will also be an <type>int</type>.
|
||||
As of PHP 8.0.0, if one of the operands cannot be interpreted a
|
||||
<classname>TypeError</classname> is thrown.
|
||||
</simpara>
|
||||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>Comparative contexts</title>
|
||||
|
||||
<simpara>
|
||||
This is the context when using a
|
||||
<link linkend="language.operators.comparison">comparison operator</link>.
|
||||
</simpara>
|
||||
|
||||
<simpara>
|
||||
The type conversions which occur in this context are explained in the
|
||||
Comparison with Various Types
|
||||
<link linkend="language.operators.comparison.types">table</link>.
|
||||
</simpara>
|
||||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>Function contexts</title>
|
||||
|
||||
<simpara>
|
||||
This is the context when a value is passed to a typed parameter, property,
|
||||
or returned from a function which declares a return type.
|
||||
</simpara>
|
||||
|
||||
<para>
|
||||
Also, because PHP supports indexing into <type>string</type>s via offsets
|
||||
using the same syntax as <type>array</type> indexing, the following example
|
||||
holds true for all PHP versions:
|
||||
In this context, when coercive typing mode is active (the default),
|
||||
only scalar values may be converted to another scalar value.
|
||||
For simple types declarations the behaviour is as follows:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<simpara>
|
||||
<type>bool</type> type declaration: value is interpreted as <type>bool</type>.
|
||||
</simpara>
|
||||
<simpara>
|
||||
<type>int</type> type declaration: value is interpreted as <type>int</type>
|
||||
if conversion is well-defined. I.e. the string is
|
||||
<link linkend="language.types.numeric-strings">numeric</link>.
|
||||
</simpara>
|
||||
<simpara>
|
||||
<type>float</type> type declaration: value is interpreted as <type>float</type>
|
||||
if conversion is well-defined. I.e. the string is
|
||||
<link linkend="language.types.numeric-strings">numeric</link>.
|
||||
</simpara>
|
||||
<simpara>
|
||||
<type>string</type> type declaration: value is interpreted as <type>string</type>.
|
||||
</simpara>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
If the type declaration is a union, see the section about
|
||||
<link linkend="language.types.declarations.union.coercive">Coercive typing with union types</link>.
|
||||
</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
$a = 'car'; // $a is a string
|
||||
$a[0] = 'b'; // $a is still a string
|
||||
echo $a; // bar
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>
|
||||
See the section titled <link linkend="language.types.string.substr">String
|
||||
access by character</link> for more information.
|
||||
</para>
|
||||
</note>
|
||||
<warning>
|
||||
<simpara>
|
||||
<!-- TODO add link to internal function definition if we have? -->
|
||||
Internal functions automatically coerce &null; to scalar types,
|
||||
this behaviour is <emphasis>DEPRECATED</emphasis> as of PHP 8.1.0.
|
||||
</simpara>
|
||||
</warning>
|
||||
</sect2>
|
||||
|
||||
<sect2 xml:id="language.types.typecasting">
|
||||
<title>Type Casting</title>
|
||||
|
||||
<para>
|
||||
Type casting in PHP works much as it does in C: the name of the desired type
|
||||
is written in parentheses before the variable which is to be cast.
|
||||
</para>
|
||||
<simpara>
|
||||
Type casting converts the value to a chosen type by writing the type within
|
||||
parentheses before the value to convert.
|
||||
</simpara>
|
||||
|
||||
<informalexample>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
$foo = 10; // $foo is an integer
|
||||
$bar = (boolean) $foo; // $bar is a boolean
|
||||
$bar = (bool) $foo; // $bar is a boolean
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>
|
||||
<simpara>
|
||||
The casts allowed are:
|
||||
</para>
|
||||
</simpara>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<simpara>(int), (integer) - cast to <type>int</type></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>(bool), (boolean) - cast to <type>bool</type></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>(float), (double), (real) - cast to <type>float</type></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>(string) - cast to <type>string</type></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>(array) - cast to <type>array</type></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>(object) - cast to <type>object</type></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>(unset) - cast to <type>NULL</type></simpara>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<simplelist>
|
||||
<member><literal>(int)</literal> - cast to <type>int</type></member>
|
||||
<member><literal>(bool)</literal> - cast to <type>bool</type></member>
|
||||
<member><literal>(float)</literal> - cast to <type>float</type></member>
|
||||
<member><literal>(string)</literal> - cast to <type>string</type></member>
|
||||
<member><literal>(array)</literal> - cast to <type>array</type></member>
|
||||
<member><literal>(object)</literal> - cast to <type>object</type></member>
|
||||
<member><literal>(unset)</literal> - cast to <type>NULL</type></member>
|
||||
</simplelist>
|
||||
|
||||
<para>
|
||||
(binary) casting and b prefix exists for forward support. Note that
|
||||
the (binary) cast is essential the same as (string), but it should not be relied
|
||||
upon.
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
<literal>(integer)</literal> is an alias of the <literal>(int)</literal> cast.
|
||||
<literal>(boolean)</literal> is an alias of the <literal>(bool)</literal> cast.
|
||||
<literal>(binary)</literal> is an alias of the <literal>(string)</literal> cast.
|
||||
<literal>(double)</literal> and <literal>(real)</literal> are aliases of
|
||||
the <literal>(float)</literal> cast.
|
||||
These casts do not use the canonical type name and are not recommended.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<para>
|
||||
The (unset) cast has been deprecated as of PHP 7.2.0. Note that the (unset) cast
|
||||
is the same as assigning the value <type>NULL</type> to the variable or call. The
|
||||
(unset) cast is removed as of PHP 8.0.0.
|
||||
</para>
|
||||
<warning>
|
||||
<simpara>
|
||||
The <literal>(real)</literal> cast alias has been deprecated as of PHP 8.0.0.
|
||||
</simpara>
|
||||
</warning>
|
||||
|
||||
<para>
|
||||
Note that tabs and spaces are allowed inside the parentheses, so the
|
||||
following are functionally equivalent:
|
||||
</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting role="php">
|
||||
<warning>
|
||||
<simpara>
|
||||
The <literal>(unset)</literal> cast has been deprecated as of PHP 7.2.0.
|
||||
Note that the <literal>(unset)</literal> cast is the same as assigning the
|
||||
value <type>NULL</type> to the variable or call.
|
||||
The <literal>(unset)</literal> cast is removed as of PHP 8.0.0.
|
||||
</simpara>
|
||||
</warning>
|
||||
|
||||
<caution>
|
||||
<simpara>
|
||||
The <literal>(binary)</literal> cast and <literal>b</literal> prefix exists
|
||||
for forward support. Currently <literal>(binary)</literal> and
|
||||
<literal>(string)</literal> are identical, however this may change and
|
||||
should not be relied upon.
|
||||
</simpara>
|
||||
</caution>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
Whitespaces are ignored within the parentheses of a cast.
|
||||
Therefore, the following are two casts are equivalent:
|
||||
<informalexample>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
$foo = (int) $bar;
|
||||
$foo = ( int ) $bar;
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<para>
|
||||
<informalexample>
|
||||
<simpara>
|
||||
Casting literal <type>string</type>s and variables to binary
|
||||
<type>string</type>s:
|
||||
</para>
|
||||
</simpara>
|
||||
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
|
@ -191,11 +276,12 @@ $binary = b"binary string";
|
|||
</programlisting>
|
||||
</informalexample>
|
||||
|
||||
<!-- TODO Remove or move into string context section? -->
|
||||
<note>
|
||||
<para>
|
||||
<simpara>
|
||||
Instead of casting a variable to a <type>string</type>, it is also possible
|
||||
to enclose the variable in double quotes.
|
||||
</para>
|
||||
</simpara>
|
||||
|
||||
<informalexample>
|
||||
<programlisting role="php">
|
||||
|
@ -218,60 +304,56 @@ if ($fst === $str) {
|
|||
<para>
|
||||
It may not be obvious exactly what will happen when casting between certain
|
||||
types. For more information, see these sections:
|
||||
<simplelist>
|
||||
<member><link linkend="language.types.boolean.casting">Converting to boolean</link></member>
|
||||
<member><link linkend="language.types.integer.casting">Converting to integer</link></member>
|
||||
<member><link linkend="language.types.float.casting">Converting to float</link></member>
|
||||
<member><link linkend="language.types.string.casting">Converting to string</link></member>
|
||||
<member><link linkend="language.types.array.casting">Converting to array</link></member>
|
||||
<member><link linkend="language.types.object.casting">Converting to object</link></member>
|
||||
<member><link linkend="language.types.resource.casting">Converting to resource</link></member>
|
||||
<member><link linkend="language.types.null.casting">Converting to NULL</link></member>
|
||||
<member><link linkend="types.comparisons">The type comparison tables</link></member>
|
||||
</simplelist>
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<simpara>
|
||||
<link linkend="language.types.boolean.casting">Converting to boolean</link>
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
<link linkend="language.types.integer.casting">Converting to integer</link>
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
<link linkend="language.types.float.casting">Converting to float</link>
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
<link linkend="language.types.string.casting">Converting to string</link>
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
<link linkend="language.types.array.casting">Converting to array</link>
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
<link linkend="language.types.object.casting">Converting to object</link>
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
<link linkend="language.types.resource.casting">Converting to
|
||||
resource</link>
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
<link linkend="language.types.null.casting">Converting to NULL</link>
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
<link linkend="types.comparisons">The type comparison tables</link>
|
||||
</simpara>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
</sect2>
|
||||
|
||||
<simplesect>
|
||||
<!-- when can this happen? TODO Remove? -->
|
||||
<note>
|
||||
<simpara>
|
||||
The behaviour of an automatic conversion to <type>array</type> is currently
|
||||
undefined.
|
||||
</simpara>
|
||||
</note>
|
||||
|
||||
<note>
|
||||
<simpara>
|
||||
Also, because PHP supports indexing into <type>string</type>s via offsets
|
||||
using the same syntax as <type>array</type> indexing, the following example
|
||||
holds true for all PHP versions:
|
||||
</simpara>
|
||||
|
||||
<informalexample>
|
||||
<programlisting role="php">
|
||||
<![CDATA[
|
||||
<?php
|
||||
$a = 'car'; // $a is a string
|
||||
$a[0] = 'b'; // $a is still a string
|
||||
echo $a; // bar
|
||||
?>
|
||||
]]>
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
|
||||
<simpara>
|
||||
See the section titled <link linkend="language.types.string.substr">String
|
||||
access by character</link> for more information.
|
||||
</simpara>
|
||||
</note>
|
||||
</simplesect>
|
||||
|
||||
</sect1>
|
||||
|
||||
<!-- Keep this comment at the end of the file
|
||||
Local variables:
|
||||
mode: sgml
|
||||
|
|
Loading…
Reference in a new issue