language/types/type-juggling.xml
e587d0655e426f97b3fcb431453da5030e743b23
e587d0655e426f97b3fcb431453da5030e743b23
...
...
@@ -81,6 +81,8 @@
81
81
82
82
<simpara>
83
83
In this context the value will be interpreted as <type>string</type>.
84
+
If the value cannot be interpreted a <classname>TypeError</classname> is thrown.
85
+
Prior to PHP 7.4.0, an <constant>E_RECOVERABLE_ERROR</constant> was raised.
84
86
</simpara>
85
87
</sect2>
86
88
...
...
@@ -102,7 +104,7 @@
102
104
<title>Integral and string contexts</title>
103
105
104
106
<simpara>
105
-
This is the context when using a
107
+
This is the context when using
106
108
<link linkend="language.operators.bitwise">bitwise operators</link>.
107
109
</simpara>
108
110
...
...
@@ -131,7 +133,7 @@
131
133
</simpara>
132
134
</sect2>
133
135
134
-
<sect2>
136
+
<sect2 xml:id="language.types.type-juggling.function">
135
137
<title>Function contexts</title>
136
138
137
139
<simpara>
...
...
@@ -140,9 +142,28 @@
140
142
</simpara>
141
143
142
144
<para>
143
-
In this context, when coercive typing mode is active (the default),
144
-
only scalar values may be converted to another scalar value.
145
-
For simple types declarations the behaviour is as follows:
145
+
In this context the value must be a value of the type.
146
+
Two exceptions exist, the first one is: if the value is of type
147
+
<type>int</type> and the declared type is <type>float</type>, then the
148
+
integer is converted to a floating point number.
149
+
The second one is: if the declared type is a <emphasis>scalar</emphasis>
150
+
<!-- e.g. An object that implements __toString will pass a string type -->
151
+
type, the value is convertable to a scalar type,
152
+
and the coercive typing mode is active
153
+
(the default), the value may be converted to an accepted scalar value.
154
+
See below for a description of this behaviour.
155
+
</para>
156
+
157
+
<warning>
158
+
<simpara>
159
+
<link linkend="functions.internal">Internal functions</link>
160
+
automatically coerce &null; to scalar types,
161
+
this behaviour is <emphasis>DEPRECATED</emphasis> as of PHP 8.1.0.
162
+
</simpara>
163
+
</warning>
164
+
165
+
<sect3 xml:id="language.types.type-juggling.function.simple">
166
+
<title>Coercive typing with simple type declarations</title>
146
167
<itemizedlist>
147
168
<listitem>
148
169
<simpara>
...
...
@@ -152,14 +173,14 @@
152
173
<listitem>
153
174
<simpara>
154
175
<type>int</type> type declaration: value is interpreted as <type>int</type>
155
-
if conversion is well-defined. I.e. the string is
176
+
if the conversion is well-defined. For example the string is
156
177
<link linkend="language.types.numeric-strings">numeric</link>.
157
178
</simpara>
158
179
</listitem>
159
180
<listitem>
160
181
<simpara>
161
182
<type>float</type> type declaration: value is interpreted as <type>float</type>
162
-
if conversion is well-defined. I.e. the string is
183
+
if the conversion is well-defined. For example the string is
163
184
<link linkend="language.types.numeric-strings">numeric</link>.
164
185
</simpara>
165
186
</listitem>
...
...
@@ -169,18 +190,95 @@
169
190
</simpara>
170
191
</listitem>
171
192
</itemizedlist>
193
+
</sect3>
172
194
173
-
If the type declaration is a union, see the section about
174
-
<link linkend="language.types.declarations.union.coercive">Coercive typing with union types</link>.
175
-
</para>
195
+
<sect3 xml:id="language.types.type-juggling.function.union">
196
+
<title>Coercive typing with union types</title>
197
+
<para>
198
+
When <literal>strict_types</literal> is not enabled, scalar type declarations
199
+
are subject to limited implicit type coercions.
200
+
If the exact type of the value is not part of the union, then the target type
201
+
is chosen in the following order of preference:
202
+
203
+
<orderedlist>
204
+
<listitem>
205
+
<simpara>
206
+
<type>int</type>
207
+
</simpara>
208
+
</listitem>
209
+
<listitem>
210
+
<simpara>
211
+
<type>float</type>
212
+
</simpara>
213
+
</listitem>
214
+
<listitem>
215
+
<simpara>
216
+
<type>string</type>
217
+
</simpara>
218
+
</listitem>
219
+
<listitem>
220
+
<simpara>
221
+
<type>bool</type>
222
+
</simpara>
223
+
</listitem>
224
+
</orderedlist>
225
+
226
+
If the type exists in the union and the value can be coerced to the
227
+
type under PHP's existing type-checking semantics, then the type is chosen.
228
+
Otherwise, the next type is tried.
229
+
</para>
230
+
231
+
<caution>
232
+
<para>
233
+
As an exception, if the value is a string and both int and float are part
234
+
of the union, the preferred type is determined by the existing
235
+
<link linkend="language.types.numeric-strings">numeric string</link>
236
+
semantics.
237
+
For example, for <literal>"42"</literal> <type>int</type> is chosen,
238
+
while for <literal>"42.0"</literal> <type>float</type> is chosen.
239
+
</para>
240
+
</caution>
241
+
242
+
<note>
243
+
<para>
244
+
Types that are not part of the above preference list are not eligible
245
+
targets for implicit coercion. In particular no implicit coercions to
246
+
the <type>null</type>, <type>false</type>, and <type>true</type>
247
+
types occur.
248
+
</para>
249
+
</note>
250
+
251
+
<example>
252
+
<title>Example of types being coerced into a type part of the union</title>
253
+
<programlisting>
254
+
<![CDATA[
255
+
<?php
256
+
// int|string
257
+
42 --> 42 // exact type
258
+
"42" --> "42" // exact type
259
+
new ObjectWithToString --> "Result of __toString()"
260
+
// object never compatible with int, fall back to string
261
+
42.0 --> 42 // float compatible with int
262
+
42.1 --> 42 // float compatible with int
263
+
1e100 --> "1.0E+100" // float too large for int type, fall back to string
264
+
INF --> "INF" // float too large for int type, fall back to string
265
+
true --> 1 // bool compatible with int
266
+
[] --> TypeError // array not compatible with int or string
267
+
268
+
// int|float|bool
269
+
"45" --> 45 // int numeric string
270
+
"45.0" --> 45.0 // float numeric string
271
+
272
+
"45X" --> true // not numeric string, fall back to bool
273
+
"" --> false // not numeric string, fall back to bool
274
+
"X" --> true // not numeric string, fall back to bool
275
+
[] --> TypeError // array not compatible with int, float or bool
276
+
?>
277
+
]]>
278
+
</programlisting>
279
+
</example>
280
+
</sect3>
176
281
177
-
<warning>
178
-
<simpara>
179
-
<link linkend="functions.internal">Internal functions</link>
180
-
automatically coerce &null; to scalar types,
181
-
this behaviour is <emphasis>DEPRECATED</emphasis> as of PHP 8.1.0.
182
-
</simpara>
183
-
</warning>
184
282
</sect2>
185
283
186
284
<sect2 xml:id="language.types.typecasting">
...
...
@@ -191,16 +289,19 @@
191
289
parentheses before the value to convert.
192
290
</simpara>
193
291
194
-
<informalexample>
292
+
<example>
293
+
<title>Type Casting</title>
195
294
<programlisting role="php">
196
295
<![CDATA[
197
296
<?php
198
-
$foo = 10; // $foo is an integer
199
-
$bar = (bool) $foo; // $bar is a boolean
297
+
$foo = 10; // $foo is an integer
298
+
$bar = (bool) $foo; // $bar is a boolean
299
+
300
+
var_dump($bar);
200
301
?>
201
302
]]>
202
303
</programlisting>
203
-
</informalexample>
304
+
</example>
204
305
205
306
<simpara>
206
307
The casts allowed are:
...
...
@@ -254,7 +355,7 @@ $bar = (bool) $foo; // $bar is a boolean
254
355
<note>
255
356
<para>
256
357
Whitespaces are ignored within the parentheses of a cast.
257
-
Therefore, the following are two casts are equivalent:
358
+
Therefore, the following two casts are equivalent:
258
359
<informalexample>
259
360
<programlisting role="php">
260
361
<![CDATA[
...
...
@@ -285,14 +386,14 @@ $binary = b"binary string";
285
386
</informalexample>
286
387
287
388
<!-- TODO Remove or move into string context section? -->
288
-
<note>
289
-
<simpara>
290
-
Instead of casting a variable to a <type>string</type>, it is also possible
291
-
to enclose the variable in double quotes.
292
-
</simpara>
389
+
<simpara>
390
+
Instead of casting a variable to a <type>string</type>, it is also possible
391
+
to enclose the variable in double quotes.
392
+
</simpara>
293
393
294
-
<informalexample>
295
-
<programlisting role="php">
394
+
<example>
395
+
<title>Different Casting Mechanisms</title>
396
+
<programlisting role="php">
296
397
<![CDATA[
297
398
<?php
298
399
$foo = 10; // $foo is an integer
...
...
@@ -301,13 +402,12 @@ $fst = (string) $foo; // $fst is also a string
301
402
302
403
// This prints out that "they are the same"
303
404
if ($fst === $str) {
304
-
echo "they are the same";
405
+
echo "they are the same", PHP_EOL;
305
406
}
306
407
?>
307
408
]]>
308
-
</programlisting>
309
-
</informalexample>
310
-
</note>
409
+
</programlisting>
410
+
</example>
311
411
312
412
<para>
313
413
It may not be obvious exactly what will happen when casting between certain
...
...
@@ -324,9 +424,7 @@ if ($fst === $str) {
324
424
<member><link linkend="types.comparisons">The type comparison tables</link></member>
325
425
</simplelist>
326
426
</para>
327
-
</sect2>
328
427
329
-
<simplesect>
330
428
<note>
331
429
<simpara>
332
430
Because PHP supports indexing into <type>string</type>s via offsets
...
...
@@ -334,7 +432,8 @@ if ($fst === $str) {
334
432
holds true for all PHP versions:
335
433
</simpara>
336
434
337
-
<informalexample>
435
+
<example>
436
+
<title>Using Array Offset with a String</title>
338
437
<programlisting role="php">
339
438
<![CDATA[
340
439
<?php
...
...
@@ -344,14 +443,14 @@ echo $a; // bar
344
443
?>
345
444
]]>
346
445
</programlisting>
347
-
</informalexample>
446
+
</example>
348
447
349
448
<simpara>
350
449
See the section titled <link linkend="language.types.string.substr">String
351
450
access by character</link> for more information.
352
451
</simpara>
353
452
</note>
354
-
</simplesect>
453
+
</sect2>
355
454
356
455
</sect1>
357
456
<!-- Keep this comment at the end of the file
358
457