PHP foreach Loop
last modified October 22, 2026
The PHP foreach loop provides an easy way to iterate over arrays
and objects. It automatically advances through each element, so there is no
index to manage.
foreach syntax
The foreach loop has two forms. The first iterates over the
values only. The second provides both keys and values.
foreach ($array as $value) { ... }
foreach ($array as $key => $value) { ... }
The loop variables are ordinary variables that remain available after the loop ends. The loop works on a copy of the array, so changing the array's contents inside a value-only loop does not affect the iteration.
Iterating over values
This example iterates over a simple indexed array and prints each value.
<?php
declare(strict_types=1);
$colors = ['red', 'green', 'blue', 'yellow'];
foreach ($colors as $color) {
echo "$color ";
}
On each iteration, the current element's value is assigned to
$color. The loop runs once for every element in the array, in
order. The trailing space in the string separates the words in the output.
$ php basic_foreach.php red green blue yellow
Iterating over keys and values
The $key => $value form gives access to both the key and the
value. This is the usual form for associative arrays.
<?php
declare(strict_types=1);
$capitals = [
'France' => 'Paris',
'Germany' => 'Berlin',
'Italy' => 'Rome'
];
foreach ($capitals as $country => $capital) {
echo "The capital of $country is $capital\n";
}
The keys are the country names and the values are the capitals. Both are assigned on every iteration, and the output follows the insertion order of the array.
$ php foreach_keys.php The capital of France is Paris The capital of Germany is Berlin The capital of Italy is Rome
Modifying array elements by reference
By default, the loop variable is a copy of the element, so assigning to it does
not change the array. Putting & before the loop variable makes
it a reference to the element, so changes are written back to the array.
<?php
declare(strict_types=1);
$numbers = [1, 2, 3, 4, 5];
foreach ($numbers as &$number) {
$number *= 2;
}
unset($number);
print_r($numbers);
Each value is doubled through the reference. The unset($number)
call after the loop is important; it breaks the reference to the last element.
Without it, the variable still points at the last element and can cause the
pitfall described in the next section.
$ php foreach_modify.php
Array
(
[0] => 2
[1] => 4
[2] => 6
[3] => 8
[4] => 10
)
Reference pitfall
If the reference is not unset and the same variable name is reused in a second loop, the last element of the array is overwritten on every iteration of that second loop. This example shows the effect.
<?php
$a = [1, 2, 3];
foreach ($a as &$v) {}
foreach ($a as $v) {}
print_r($a);
The first loop leaves $v referencing the last element. The second
loop assigns each value to $v, which writes into that last element.
The result is [1, 2, 2], not [1, 2, 3].
$ php foreach_pitfall.php
Array
(
[0] => 1
[1] => 2
[2] => 2
)
Nested loops with multidimensional arrays
An array can contain other arrays. Nested foreach loops process
each row and then each cell in that row.
<?php
declare(strict_types=1);
$matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
foreach ($matrix as $row) {
foreach ($row as $cell) {
echo "$cell ";
}
echo "\n";
}
The outer loop visits each row. The inner loop visits each cell of the current
row. The echo "\n" after the inner loop starts a new line for each
row.
$ php foreach_multidimensional.php 1 2 3 4 5 6 7 8 9
Destructuring with list
When each element is itself an array, list() (or the short
[...] syntax) unpacks its items into separate variables inside
the foreach header.
<?php
declare(strict_types=1);
$people = [
['John', 'Doe', 30],
['Jane', 'Smith', 25],
['Bob', 'Johnson', 45]
];
foreach ($people as list($firstName, $lastName, $age)) {
echo "$firstName $lastName is $age years old\n";
}
Each sub-array is split into $firstName, $lastName,
and $age. The number of variables must match the structure of the
sub-arrays.
$ php foreach_list.php John Doe is 30 years old Jane Smith is 25 years old Bob Johnson is 45 years old
Breaking and continuing
The continue statement skips the rest of the current iteration.
The break statement ends the loop.
<?php
declare(strict_types=1);
$values = [10, 20, 30, 40, 50, 60];
foreach ($values as $value) {
if ($value == 30) {
continue;
}
if ($value == 50) {
break;
}
echo "$value ";
}
The value 30 is skipped by continue. The loop stops at 50 because
of break, so 60 is never reached. Only 10, 20, and 40 are printed.
$ php foreach_control.php 10 20 40
Iterating over object properties
When foreach is applied to an object, it iterates over the
object's accessible properties. Outside the class, only public properties are
visible.
<?php
declare(strict_types=1);
class Book {
public $title = 'PHP Guide';
public $author = 'John Doe';
public $price = 29.99;
}
$book = new Book();
foreach ($book as $property => $value) {
echo "$property: $value\n";
}
The property names become the keys and their values become the values. To
customize iteration over an object, implement the Iterator or
IteratorAggregate interface.
$ php foreach_object.php title: PHP Guide author: John Doe price: 29.99
Alternative syntax
PHP also supports a colon-based syntax, which is common in templates that mix
PHP and HTML. The loop ends with endforeach.
<?php
$fruits = ['apple', 'banana'];
foreach ($fruits as $fruit):
echo "$fruit\n";
endforeach;
The colon replaces the opening brace, and endforeach replaces the
closing brace. The behavior is identical to the braced form.
$ php foreach_alt.php apple banana
Empty arrays
If the array is empty, the loop body never runs. No error is raised.
<?php
$empty = [];
foreach ($empty as $item) {
echo "never printed\n";
}
echo "done\n";
The body is skipped and execution continues after the loop. This is why
foreach is safe to use on arrays that may have no elements.
$ php foreach_empty.php done
Non-array values
foreach works only on arrays and objects. Passing any other type
produces a warning, and the loop body is not executed. The script itself keeps
running. The warning text is shown on the output of the PHP CLI; its exact
wording and location depend on your configuration.
<?php
$value = 42;
foreach ($value as $item) {
echo $item;
}
echo "after\n";
Because $value is an integer, the loop cannot iterate over it. The
script still reaches the final echo. Check with is_iterable
before looping over values of unknown type.
$ php foreach_nonarray.php after
Best practices
- References: Unset the reference variable after a loop that uses
&. - Readability: Use meaningful names for keys and values.
- Safety: Avoid changing the structure of the array you are iterating over.
- Type checks: Use
is_iterableoriterabletype hints when the input type varies.
Source
In this article we have covered the foreach loop with examples of
value and key iteration, reference modification, nested arrays, destructuring,
object iteration, and common pitfalls.
Author
List all PHP tutorials.