Step 1 of 5 · Reading · ~4 min
Learn
Control Flow
Loops
Four loop forms, one job: run a block more than once. Choosing between them is mostly a question of what you already know before you start.
| Loop | Reach for it when |
|---|---|
foreach | You have an array and want every element — the default choice |
for | You need a counter, or you know exactly how many passes |
while | You repeat until a condition flips, and the count is unknown |
do ... while | Same, but the body must run at least once |
foreach — the workhorse
<?php
$weights = [1.75, 12.5, 0.4];
foreach ($weights as $kg) {
echo $kg, "\n";
}
$depot = ["Lisbon" => 12, "Porto" => 5];
foreach ($depot as $city => $count) {
echo "$city holds $count parcels\n";
}
//> 1.75
//> 12.5
//> 0.4
//> Lisbon holds 12 parcels
//> Porto holds 5 parcels
One variable gives you values; the two-variable as $key => $value form gives you both. You never manage an index, so you can never run off the end of the array.
Typing tip: => is an equals sign then a greater-than sign, no space between. Do not confuse it with ->, which is a hyphen then a greater-than sign and is used for object members.
for — the accumulator pattern
This shape appears in more exercises than any other: a running total declared before the loop, updated inside it, and printed after it.
<?php
$sum = 0;
for ($i = 1; $i <= 5; $i++) {
$sum += $i;
}
echo $sum, "\n";
//> 15
Three parts separated by semicolons: where to start, the keep-going test, and the step. Declaring $sum inside the loop would reset it on every pass; printing inside the loop would print five lines instead of one.
The off-by-one
| Condition | For n = 5 it visits | Total |
|---|---|---|
✓ $i <= $n | 1, 2, 3, 4, 5 | 15 |
✗ $i < $n | 1, 2, 3, 4 | 10 |
< stops one short. Say out loud what the last value should be, then pick the operator that includes it.
while and do ... while
<?php
$n = 16;
$halvings = 0;
while ($n > 1) {
$n = intdiv($n, 2);
$halvings++;
}
echo $halvings, "\n";
$tries = 0;
do {
$tries++;
} while ($tries < 0);
echo $tries, "\n";
//> 4
//> 1
while checks first, so a condition that starts out false means zero passes. do ... while checks last, so the body always runs at least once — the counter reaches 1 even though its condition was false from the very beginning.
break and continue
continue skips the rest of this pass; break leaves the loop entirely. Both accept an optional level, so break 2; exits two nested loops at once.
<?php
foreach ([4, 7, 9, 12] as $n) {
if ($n % 2 !== 0) continue; // skip the odd ones
if ($n > 10) break; // stop once they get large
echo $n, "\n";
}
//> 4
The by-reference trap
foreach ($arr as &$v) lets you modify elements in place — and it leaves $v still pointing at the last element after the loop ends. The next loop that reuses that name overwrites it.
<?php
$vals = ["a", "b", "c"];
foreach ($vals as &$v) { $v = strtoupper($v); }
foreach ($vals as $v) { } // reuses $v and silently corrupts the array
print_r($vals);
//> Array
//> (
//> [0] => A
//> [1] => B
//> [2] => B
//> )
| ✗ | ✓ |
|---|---|
foreach ($a as &$v) {...} then reuse $v | foreach ($a as &$v) {...} then unset($v); |
The fix is one line: unset($v); immediately after any by-reference loop. Better still, avoid & unless you truly need to mutate in place — array_map covers most of those cases and is coming up shortly.
Your exercise
Sum 1 to N reads one positive integer and prints 1 + 2 + ... + N.
Use the accumulator pattern above: $sum = 0; before the loop, $sum += $i; inside it, echo $sum, "\n"; after it. The mistake the grader catches is the boundary — the first test feeds 5 and expects 15, and with $i < $n you print 10 and fail immediately. The hidden case feeds 100 and expects 5050, so the loop has to be real rather than a few hand-written additions. Print the number alone, then a newline.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…