language/control-structures/foreach.xml
53a400680d0cb2ddabd4493fb9846533c422e90d
53a400680d0cb2ddabd4493fb9846533c422e90d
...
...
@@ -1,213 +1,129 @@
1
1
<?xml version="1.0" encoding="utf-8"?>
2
2
<!-- $Revision$ -->
3
-
4
3
<sect1 xml:id="control-structures.foreach" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
5
-
<title><literal>foreach</literal></title>
4
+
<title>foreach</title>
6
5
<?phpdoc print-version-for="foreach"?>
7
6
<para>
8
7
The <literal>foreach</literal> construct provides an easy way to
9
-
iterate over arrays. <literal>foreach</literal> works only on arrays
10
-
and objects, and will issue an error when you try to use it on a variable
11
-
with a different data type or an uninitialized variable. There are two
12
-
syntaxes:
8
+
iterate over <type>array</type>s and <interfacename>Traversable</interfacename> objects.
9
+
<literal>foreach</literal> will issue an error when used with
10
+
a variable containing a different data type or with an uninitialized variable.
13
11
<informalexample>
12
+
<simpara>
13
+
<literal>foreach</literal> can optionally get the <literal>key</literal> of each element:
14
+
</simpara>
14
15
<programlisting>
15
16
<![CDATA[
16
-
foreach (array_expression as $value)
17
-
statement
18
-
foreach (array_expression as $key => $value)
19
-
statement
17
+
foreach (iterable_expression as $value) {
18
+
statement_list
19
+
}
20
+
21
+
foreach (iterable_expression as $key => $value) {
22
+
statement_list
23
+
}
20
24
]]>
21
25
</programlisting>
22
26
</informalexample>
23
27
</para>
24
28
<simpara>
25
-
The first form loops over the array given by
26
-
<literal>array_expression</literal>. On each iteration, the value of
27
-
the current element is assigned to <literal>$value</literal> and
28
-
the internal array pointer is advanced by one (so on the next
29
-
iteration, you'll be looking at the next element).
29
+
The first form traverses the iterable given by
30
+
<literal>iterable_expression</literal>. On each iteration, the value of
31
+
the current element is assigned to <literal>$value</literal>.
30
32
</simpara>
31
33
<simpara>
32
34
The second form will additionally assign the current element's key to
33
35
the <literal>$key</literal> variable on each iteration.
34
36
</simpara>
37
+
<simpara>
38
+
Note that <literal>foreach</literal> does not modify the internal array
39
+
pointer, which is used by functions such as <function>current</function>
40
+
and <function>key</function>.
41
+
</simpara>
35
42
<simpara>
36
43
It is possible to
37
44
<link linkend="language.oop5.iterations">customize object iteration</link>.
38
45
</simpara>
39
-
<para>
40
-
<note>
41
-
<para>
42
-
In PHP 5, when <literal>foreach</literal> first starts executing, the
43
-
internal array pointer is automatically reset to the first element of the
44
-
array. This means that you do not need to call <function>reset</function>
45
-
before a <literal>foreach</literal> loop.
46
-
</para>
47
-
<para>
48
-
As <literal>foreach</literal> relies on the internal array pointer in PHP
49
-
5, changing it within the loop may lead to unexpected behavior.
50
-
</para>
51
-
<para>
52
-
In PHP 7, <literal>foreach</literal> does not use the internal array
53
-
pointer.
54
-
</para>
55
-
</note>
56
-
</para>
57
-
<para>
58
-
In order to be able to directly modify array elements within the loop precede
59
-
<literal>$value</literal> with &. In that case the value will be assigned by
60
-
<link linkend="language.references">reference</link>.
61
-
<informalexample>
62
-
<programlisting role="php">
63
-
<![CDATA[
64
-
<?php
65
-
$arr = array(1, 2, 3, 4);
66
-
foreach ($arr as &$value) {
67
-
$value = $value * 2;
68
-
}
69
-
// $arr is now array(2, 4, 6, 8)
70
-
unset($value); // break the reference with the last element
71
-
?>
72
-
]]>
73
-
</programlisting>
74
-
</informalexample>
75
-
</para>
76
-
<warning>
77
-
<para>
78
-
Reference of a <literal>$value</literal> and the last array element
79
-
remain even after the <literal>foreach</literal> loop. It is recommended
80
-
to destroy it by <function>unset</function>.
81
-
Otherwise you will experience the following behavior:
82
-
</para>
83
-
<informalexample>
84
-
<programlisting role="php">
85
-
<![CDATA[
86
-
<?php
87
-
$arr = array(1, 2, 3, 4);
88
-
foreach ($arr as &$value) {
89
-
$value = $value * 2;
90
-
}
91
-
// $arr is now array(2, 4, 6, 8)
92
-
93
-
// without an unset($value), $value is still a reference to the last item: $arr[3]
94
46
95
-
foreach ($arr as $key => $value) {
96
-
// $arr[3] will be updated with each value from $arr...
97
-
echo "{$key} => {$value} ";
98
-
print_r($arr);
99
-
}
100
-
// ...until ultimately the second-to-last value is copied onto the last value
101
-
102
-
// output:
103
-
// 0 => 2 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 2 )
104
-
// 1 => 4 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 4 )
105
-
// 2 => 6 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 6 )
106
-
// 3 => 6 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 6 )
107
-
?>
108
-
]]>
109
-
</programlisting>
110
-
</informalexample>
111
-
</warning>
112
-
<para>
113
-
Before PHP 5.5.0, referencing <literal>$value</literal> is only possible if the iterated array can be
114
-
referenced (i.e. if it is a variable). The following code works only as of PHP 5.5.0:
115
-
<informalexample>
116
-
<programlisting role="php">
47
+
<example>
48
+
<title>Common <literal>foreach</literal> usages</title>
49
+
<programlisting role="php">
117
50
<![CDATA[
118
51
<?php
119
-
foreach (array(1, 2, 3, 4) as &$value) {
120
-
$value = $value * 2;
121
-
}
122
-
?>
123
-
]]>
124
-
</programlisting>
125
-
</informalexample>
126
-
</para>
127
-
<para>
128
-
<note>
129
-
<para>
130
-
<literal>foreach</literal> does not support the ability to
131
-
suppress error messages using '@'.
132
-
</para>
133
-
</note>
134
-
</para>
135
-
<para>
136
-
Some more examples to demonstrate usage:
137
-
<informalexample>
138
-
<programlisting role="php">
139
-
<![CDATA[
140
-
<?php
141
-
/* foreach example 1: value only */
142
-
143
-
$a = array(1, 2, 3, 17);
144
-
145
-
foreach ($a as $v) {
146
-
echo "Current value of \$a: $v.\n";
147
-
}
148
-
149
-
/* foreach example 2: value (with its manual access notation printed for illustration) */
150
52
151
-
$a = array(1, 2, 3, 17);
53
+
/* Example: value only */
54
+
$array = [1, 2, 3, 17];
152
55
153
-
$i = 0; /* for illustrative purposes only */
154
-
155
-
foreach ($a as $v) {
156
-
echo "\$a[$i] => $v.\n";
157
-
$i++;
56
+
foreach ($array as $value) {
57
+
echo "Current element of \$array: $value.\n";
158
58
}
159
59
160
-
/* foreach example 3: key and value */
161
-
162
-
$a = array(
60
+
/* Example: key and value */
61
+
$array = [
163
62
"one" => 1,
164
63
"two" => 2,
165
64
"three" => 3,
166
65
"seventeen" => 17
167
-
);
66
+
];
168
67
169
-
foreach ($a as $k => $v) {
170
-
echo "\$a[$k] => $v.\n";
68
+
foreach ($array as $key => $value) {
69
+
echo "Key: $key => Value: $value\n";
171
70
}
172
71
173
-
/* foreach example 4: multi-dimensional arrays */
174
-
$a = array();
175
-
$a[0][0] = "a";
176
-
$a[0][1] = "b";
177
-
$a[1][0] = "y";
178
-
$a[1][1] = "z";
72
+
/* Example: multi-dimensional key-value arrays */
73
+
$grid = [];
74
+
$grid[0][0] = "a";
75
+
$grid[0][1] = "b";
76
+
$grid[1][0] = "y";
77
+
$grid[1][1] = "z";
179
78
180
-
foreach ($a as $v1) {
181
-
foreach ($v1 as $v2) {
182
-
echo "$v2\n";
79
+
foreach ($grid as $y => $row) {
80
+
foreach ($row as $x => $value) {
81
+
echo "Value at position x=$x and y=$y: $value\n";
183
82
}
184
83
}
185
84
186
-
/* foreach example 5: dynamic arrays */
187
-
188
-
foreach (array(1, 2, 3, 4, 5) as $v) {
189
-
echo "$v\n";
85
+
/* Example: dynamic arrays */
86
+
foreach (range(1, 5) as $value) {
87
+
echo "$value\n";
190
88
}
191
89
?>
192
90
]]>
193
-
</programlisting>
194
-
</informalexample>
195
-
</para>
91
+
</programlisting>
92
+
</example>
93
+
<note>
94
+
<para>
95
+
<literal>foreach</literal> does not support the ability to
96
+
suppress error messages using the
97
+
<link linkend="language.operators.errorcontrol"><literal>@</literal></link>.
98
+
</para>
99
+
</note>
196
100
197
101
<sect2 xml:id="control-structures.foreach.list">
198
-
<title>Unpacking nested arrays with list()</title>
102
+
<title>Unpacking nested arrays</title>
199
103
<?phpdoc print-version-for="foreach.list"?>
200
-
201
104
<para>
202
-
PHP 5.5 added the ability to iterate over an array of arrays and unpack the
203
-
nested array into loop variables by providing a <function>list</function>
204
-
as the value.
105
+
It is possible to iterate over an array of arrays and unpack the nested array
106
+
into loop variables by using either
107
+
<link linkend="language.types.array.syntax.destructuring">array destructuring</link>
108
+
via <literal>[]</literal> or by using the <function>list</function> language
109
+
construct as the value.
110
+
111
+
<note>
112
+
<simpara>
113
+
Please note that
114
+
<link linkend="language.types.array.syntax.destructuring">array destructuring</link>
115
+
via <literal>[]</literal> is only possible as of PHP 7.1.0
116
+
</simpara>
117
+
</note>
205
118
</para>
206
119
207
120
<para>
208
-
For example:
209
-
210
121
<informalexample>
122
+
<simpara>
123
+
In both of the following examples <literal>$a</literal> will be set to
124
+
the first element of the nested array and <literal>$b</literal> will
125
+
contain the second element:
126
+
</simpara>
211
127
<programlisting role="php">
212
128
<![CDATA[
213
129
<?php
...
...
@@ -216,9 +132,11 @@ $array = [
216
132
[3, 4],
217
133
];
218
134
135
+
foreach ($array as [$a, $b]) {
136
+
echo "A: $a; B: $b\n";
137
+
}
138
+
219
139
foreach ($array as list($a, $b)) {
220
-
// $a contains the first element of the nested array,
221
-
// and $b contains the second element.
222
140
echo "A: $a; B: $b\n";
223
141
}
224
142
?>
...
...
@@ -235,22 +153,26 @@ A: 3; B: 4
235
153
</para>
236
154
237
155
<para>
238
-
You can provide fewer elements in the <function>list</function> than there
239
-
are in the nested array, in which case the leftover array values will be
240
-
ignored:
241
-
156
+
When providing fewer variables than there are elements in the array,
157
+
the remaining elements will be ignored.
158
+
Similarly, elements can be skipped over by using a comma:
242
159
<informalexample>
243
160
<programlisting role="php">
244
161
<![CDATA[
245
162
<?php
246
163
$array = [
247
-
[1, 2],
248
-
[3, 4],
164
+
[1, 2, 3],
165
+
[3, 4, 6],
249
166
];
250
167
251
-
foreach ($array as list($a)) {
252
-
// Note that there is no $b here.
253
-
echo "$a\n";
168
+
foreach ($array as [$a, $b]) {
169
+
// Note that there is no $c here.
170
+
echo "$a $b\n";
171
+
}
172
+
173
+
foreach ($array as [, , $c]) {
174
+
// Skipping over $a and $b
175
+
echo "$c\n";
254
176
}
255
177
?>
256
178
]]>
...
...
@@ -258,8 +180,10 @@ foreach ($array as list($a)) {
258
180
&example.outputs;
259
181
<screen>
260
182
<![CDATA[
261
-
1
262
-
3
183
+
1 2
184
+
3 4
185
+
5
186
+
6
263
187
]]>
264
188
</screen>
265
189
</informalexample>
...
...
@@ -278,7 +202,7 @@ $array = [
278
202
[3, 4],
279
203
];
280
204
281
-
foreach ($array as list($a, $b, $c)) {
205
+
foreach ($array as [$a, $b, $c]) {
282
206
echo "A: $a; B: $b; C: $c\n";
283
207
}
284
208
?>
...
...
@@ -287,7 +211,6 @@ foreach ($array as list($a, $b, $c)) {
287
211
&example.outputs;
288
212
<screen>
289
213
<![CDATA[
290
-
291
214
Notice: Undefined offset: 2 in example.php on line 7
292
215
A: 1; B: 2; C:
293
216
...
...
@@ -299,41 +222,89 @@ A: 3; B: 4; C:
299
222
</para>
300
223
</sect2>
301
224
302
-
<sect2 role="changelog">
303
-
&reftitle.changelog;
225
+
<sect2 xml:id="control-structures.foreach.reference">
226
+
<title>foreach and references</title>
304
227
<para>
305
-
<informaltable>
306
-
<tgroup cols="2">
307
-
<thead>
308
-
<row>
309
-
<entry>&Version;</entry>
310
-
<entry>&Description;</entry>
311
-
</row>
312
-
</thead>
313
-
<tbody>
314
-
<row>
315
-
<entry>7.0.0</entry>
316
-
<entry>
317
-
<literal>foreach</literal> does not use the internal array pointer anymore.
318
-
</entry>
319
-
</row>
320
-
<row>
321
-
<entry>5.5.0</entry>
322
-
<entry>
323
-
Referencing of <literal>$value</literal> is supported for expressions.
324
-
Formerly, only variables have been supported.
325
-
</entry>
326
-
</row>
327
-
<row>
328
-
<entry>5.5.0</entry>
329
-
<entry>
330
-
Unpacking nested arrays with <function>list</function> is supported.
331
-
</entry>
332
-
</row>
333
-
</tbody>
334
-
</tgroup>
335
-
</informaltable>
228
+
It is possible to directly modify array elements within a loop by preceding
229
+
<literal>$value</literal> with <literal>&</literal>.
230
+
In that case the value will be assigned by
231
+
<link linkend="language.references">reference</link>.
232
+
<informalexample>
233
+
<programlisting role="php">
234
+
<![CDATA[
235
+
<?php
236
+
$arr = [1, 2, 3, 4];
237
+
foreach ($arr as &$value) {
238
+
$value = $value * 2;
239
+
}
240
+
// $arr is now [2, 4, 6, 8]
241
+
unset($value); // break the reference with the last element
242
+
?>
243
+
]]>
244
+
</programlisting>
245
+
</informalexample>
336
246
</para>
247
+
<warning>
248
+
<simpara>
249
+
Reference to a <literal>$value</literal> of the last array element
250
+
remain even after the <literal>foreach</literal> loop. It is recommended
251
+
to destroy these using <function>unset</function>.
252
+
Otherwise, the following behavior will occur:
253
+
</simpara>
254
+
<informalexample>
255
+
<programlisting role="php">
256
+
<![CDATA[
257
+
<?php
258
+
$arr = [1, 2, 3, 4];
259
+
foreach ($arr as &$value) {
260
+
$value = $value * 2;
261
+
}
262
+
// $arr is now [2, 4, 6, 8]
263
+
264
+
// without an unset($value), $value is still a reference to the last item: $arr[3]
265
+
266
+
foreach ($arr as $key => $value) {
267
+
// $arr[3] will be updated with each value from $arr...
268
+
echo "{$key} => {$value} ";
269
+
print_r($arr);
270
+
}
271
+
// ...until ultimately the second-to-last value is copied onto the last value
272
+
?>
273
+
]]>
274
+
</programlisting>
275
+
&example.outputs;
276
+
<screen>
277
+
<![CDATA[
278
+
0 => 2 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 2 )
279
+
1 => 4 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 4 )
280
+
2 => 6 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 6 )
281
+
3 => 6 Array ( [0] => 2, [1] => 4, [2] => 6, [3] => 6 )
282
+
]]>
283
+
</screen>
284
+
</informalexample>
285
+
</warning>
286
+
<example>
287
+
<title>Iterate a constant array's values by reference</title>
288
+
<programlisting role="php">
289
+
<![CDATA[
290
+
<?php
291
+
foreach ([1, 2, 3, 4] as &$value) {
292
+
$value = $value * 2;
293
+
}
294
+
?>
295
+
]]>
296
+
</programlisting>
297
+
</example>
298
+
</sect2>
299
+
300
+
<sect2 role="seealso">
301
+
&reftitle.seealso;
302
+
<simplelist>
303
+
<member><link linkend="language.types.array">array</link></member>
304
+
<member><interfacename>Traversable</interfacename></member>
305
+
<member><link linkend="language.types.iterable">iterable</link></member>
306
+
<member><function>list</function></member>
307
+
</simplelist>
337
308
</sect2>
338
309
339
310
</sect1>
340
311