Skip to content
Lesson 7 of 17

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.

LoopReach for it when
foreachYou have an array and want every element — the default choice
forYou need a counter, or you know exactly how many passes
whileYou repeat until a condition flips, and the count is unknown
do ... whileSame, 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

ConditionFor n = 5 it visitsTotal
$i <= $n1, 2, 3, 4, 515
$i < $n1, 2, 3, 410

< 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 $vforeach ($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.

Up nextFunctionsFunctions

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…