Loops

Reviewed & published by Brayan K

By the end of this lesson you'll repeat work without copy-pasting — counting with for, waiting on a condition with while and do-while, and walking through arrays with foreach, the loop you'll reach for most in real PHP.

Part of the free PHP course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.

What You'll Learn in This Lesson

1️⃣ The for Loop — Counting

A loop runs the same block of code over and over so you don't have to copy-paste it. The for loop is the one to use when you know how many times to repeat. Its header has three parts inside the brackets, separated by semicolons: a start value, a condition checked before each pass, and a step that runs after each pass. The $i++ step means "add 1 to $i".

<?php
// A FOR loop is for when you know HOW MANY times to repeat.
// It has three parts inside ( ) separated by semicolons:
//   1) start:  $i = 1        — runs once, before the loop
//   2) check:  $i <= 5       — tested before every pass; loop runs while true
//   3) step:   $i++          — runs after every pass ($i++ means "add 1 to $i")

for ($i = 1; $i <= 5; $i++) {
    echo "Count: $i\n";      // PHP swaps $i for its value inside "double quotes"
}

echo "Done!\n";              // runs once, AFTER the loop finishes
?>

Read the header as: start at 1, keep going while $i <= 5, and add 1 each time. When $i hits 6 the condition is false, the loop ends, and the code after it runs once.

2️⃣ The while Loop — Repeat Until Done

Sometimes you don't know the count in advance — you just want to keep going until something happens. That's the while loop: it checks a condition before each pass and repeats as long as it's true. The golden rule: something inside the loop must move you toward the condition becoming false, or the loop never ends.

<?php
// A WHILE loop repeats as long as a condition stays true.
// Use it when you DON'T know the count up front — here we stop when a
// total passes 100. You must change something inside the loop, or it
// would run forever.

$total = 0;       // start at zero
$day = 0;         // counts how many days we added

while ($total < 100) {        // keep going WHILE total is under 100
    $day++;                   // move to the next day (add 1)
    $total += 20;             // $total += 20  is short for  $total = $total + 20
    echo "Day $day: total is $total\n";
}

echo "Reached the goal in $day days.\n";
?>

Here $total += 20 grows the total every pass, so the condition $total < 100 eventually turns false and the loop stops. Take that line out and you'd have an infinite loop.

3️⃣ The do-while Loop — Run At Least Once

A do-while loop is a while loop flipped upside down: it runs the body first, then checks the condition at the bottom. Because of that, the body always runs at least once — even if the condition was false from the very start. It's the right choice whenever the work must happen one time before you decide whether to repeat (think "show the menu, then ask if they want it again").

<?php
// A DO-WHILE loop runs the body FIRST, then checks the condition.
// So it always runs AT LEAST ONCE — even if the condition is false to begin
// with. Perfect for "show a menu, then ask again" style code.

$count = 10;

do {
    echo "Body ran with count = $count\n";   // this prints once...
    $count++;
} while ($count < 5);                          // ...even though 10 < 5 is false

echo "Notice the body ran once despite the false condition.\n";
?>

4️⃣ foreach — Walking an Array

This is the loop you'll use most in PHP. An array is an ordered list of values, and foreach hands you each one in turn — no counter, no index, no off-by-one mistakes. The simplest form is foreach ($arr as $value): on each pass, your variable (here $fruit) holds the next item.

<?php
// FOREACH is PHP's most-used loop — it walks through every item in an array.
// The simplest form gives you each VALUE in turn:  foreach ($arr as $value)

$fruits = ["Apple", "Banana", "Cherry", "Date"];

foreach ($fruits as $fruit) {        // $fruit holds one item each time round
    echo "I like $fruit\n";
}

echo "That's " . count($fruits) . " fruits.\n";   // count() = how many items
?>

5️⃣ foreach with Keys — $key => $value

Every array item has a key (its label) as well as a value. In a plain list the keys are positions — 0, 1, 2… In an associative array the keys are names you chose, like "coffee". The form foreach ($arr as $key => $value) gives you both at once: the part before => is the key, the part after is the value.

<?php
// The KEY => VALUE form gives you BOTH the key and the value each pass.
// For a list, the key is the position (0, 1, 2...).
// For an associative array (named keys), the key is the name.

$prices = ["coffee" => 3.50, "muffin" => 2.00, "juice" => 4.25];

foreach ($prices as $item => $price) {       // $item = key, $price = value
    echo "$item costs \$$price\n";          // \$ prints a literal $ sign
}

// It works on a plain list too — here the key is the index:
$colours = ["red", "green", "blue"];
foreach ($colours as $index => $colour) {
    echo "[$index] $colour\n";
}
?>

Notice 3.50 printed as 3.5 — PHP drops a trailing zero when it shows a number. To force two decimals (real money) you'd use number_format($price, 2) or printf, which you'll see in the order example below.

6️⃣ break & continue — Steering the Loop

break leaves the loop completely — handy once you've found what you were looking for. continue skips just the rest of the current pass and jumps to the next one. When loops are nested (a loop inside a loop), you can add a number: break 2 breaks out of two loops at once, and continue 2 jumps to the next pass of the outer loop.

<?php
// BREAK stops the loop completely. CONTINUE skips the rest of THIS pass
// and jumps to the next one. Both are usually paired with an if.

echo "=== break: stop at the first match ===\n";
$numbers = [3, 7, 12, 5, 20];
foreach ($numbers as $num) {
    if ($num > 10) {
        echo "Found one over 10: $num — stopping.\n";
        break;                      // leave the loop entirely
    }
    echo "Checked $num, too small.\n";
}

echo "\n=== continue: skip the even ones ===\n";
for ($i = 1; $i <= 6; $i++) {
    if ($i % 2 === 0) {             // % is remainder; even numbers give 0
        continue;                   // skip the echo, go to next $i
    }
    echo "Odd: $i\n";
}

// LEVELS: break 2 / continue 2 act on the OUTER loop, not just the inner one.
echo "\n=== break 2: leave BOTH loops at once ===\n";
for ($row = 1; $row <= 3; $row++) {
    for ($col = 1; $col <= 3; $col++) {
        if ($row === 2 && $col === 2) {
            echo "Hit ($row,$col) — break 2 leaves both loops.\n";
            break 2;                // not just the inner loop — both
        }
        echo "At ($row,$col)\n";
    }
}
?>

Now you try. The script below counts down, so the condition and step are different from a normal count-up. Fill in each ___ using the 👉 hint, then run it and check it against the Output panel.

<?php
// 🎯 YOUR TURN — print a countdown from 5 down to 1, then "Lift off!".
// A countdown goes DOWNWARDS, so the step must SUBTRACT. Fill the blanks.

for ($i = 5; $i ___ 1; $i--) {     // 👉 keep going while $i is >= 1  (use:  >= )
    echo ___;                      // 👉 echo the number then a newline, e.g.  "$i\n"
}
echo "Lift off!\n";

// ✅ Expected output:
//    5
//    4
//    3
//    2
//    1
//    Lift off!
?>

One more — this time practise the key => value form. Name the key and value variables so the echo already in the code lines up.

<?php
// 🎯 YOUR TURN — print each student and their score using KEY => VALUE.
// Fill the two blanks so PHP gives you both the name (key) and the mark (value).

$scores = ["Maya" => 88, "Owen" => 73, "Priya" => 95];

foreach ($scores as ___ => ___) {       // 👉 first blank = the key, second = the value
    echo "$name scored $score\n";       // 👉 so name your variables  $name  and  $score
}

// ✅ Expected output:
//    Maya scored 88
//    Owen scored 73
//    Priya scored 95
?>

7️⃣ Alternative Syntax — endforeach & endfor

PHP lets you swap the curly braces { } for a colon and a matching end word: foreach (…): … endforeach; and for (…): … endfor; Both forms do exactly the same thing. This style shines when a loop is wrapped around HTML in a template, because a named endforeach; is far easier to pair up than a lone } buried among tags.

<?php
// ALTERNATIVE SYNTAX: instead of { } you can use a colon and an "end" word.
// This reads much better when you mix loops with HTML in a template, because
// the closing endforeach / endfor is clearer than a lonely }.

$users = ["Ada", "Linus", "Grace"];
?>
<ul>
<?php foreach ($users as $user): ?>
    <li><?php echo $user; ?></li>
<?php endforeach; ?>
</ul>

<?php for ($n = 1; $n <= 3; $n++): ?>
<p>Row <?php echo $n; ?></p>
<?php endfor; ?>

8️⃣ Putting It Together — An Order Total

Here's the whole lesson in one realistic snippet: a foreach over a cart with named keys, a continue to skip out-of-stock items, and a running total. This is the exact shape of code you'd write to add up a real shopping basket.

<?php
// REAL-WORLD: total up an online order, skipping out-of-stock items.
// This combines foreach (key => value), continue, and a running total —
// the exact pattern you'll use on real shopping carts.

$cart = [
    "Laptop"   => 999.00,
    "Mouse"    => 25.50,
    "Keyboard" => 0,        // 0 means out of stock — we'll skip it
    "Monitor"  => 180.75,
];

$total = 0;
$lines = 0;

foreach ($cart as $product => $price) {
    if ($price <= 0) {
        echo "$product: out of stock (skipped)\n";
        continue;                       // don't add it to the total
    }
    $total += $price;
    $lines++;
    printf("%-9s \$%.2f\n", $product, $price);   // %-9s pads the name to 9 chars
}

echo "-------------------\n";
printf("Items: %d   Total: \$%.2f\n", $lines, $total);
?>

Common Errors (and the fix)

Pro Tips

📋 Quick Reference — PHP Loops

SyntaxExampleWhat It Does
for (a; b; c) { }for ($i=0; $i<5; $i++)Loop a known number of times
while (cond) { }while ($x < 10)Repeat while a condition is true
do { } while (cond);do { … } while ($x<10);Run once, then repeat while true
foreach ($a as $v)foreach ($f as $fruit)Walk each value of an array
foreach ($a as $k => $v)foreach ($p as $name => $age)Walk key and value together
break / break 2break 2;Exit one (or N nested) loops
continue / continue 2continue;Skip to the next iteration
: … endforeach; / endfor;foreach (…): … endforeach;Brace-free style for templates

Mini-Challenge: FizzBuzz

No code is filled in this time — just a brief and an outline. FizzBuzz is the most famous loop exercise in programming, and it's a rite of passage. Write it yourself, run it on onecompiler.com/php or your own machine, then check your result against the expected output in the comments.

<?php
// 🎯 MINI-CHALLENGE: FizzBuzz (the classic loop exercise).
// No code is filled in — work from the steps, then run it.
//
// 1. Loop $i from 1 to 15 with a FOR loop.
// 2. For each $i, decide what to print:
//      - divisible by 3 AND 5  -> print "FizzBuzz"
//      - divisible by 3 only   -> print "Fizz"
//      - divisible by 5 only   -> print "Buzz"
//      - otherwise             -> print the number $i
//    (Tip: "divisible by 3" means  $i % 3 === 0 . Check 3-AND-5 FIRST.)
// 3. Put each result on its own line (end with \n).
//
// ✅ Expected output:
//    1
//    2
//    Fizz
//    4
//    Buzz
//    Fizz
//    7
//    8
//    Fizz
//    Buzz
//    11
//    Fizz
//    13
//    14
//    FizzBuzz

// your code here
?>

🎉 Lesson Complete!

Practice quiz

Which loop is best when you know exactly how many times to repeat?

  • while
  • do-while
  • for
  • foreach

Answer: for. A for loop, with its start/condition/step header, is ideal for a known number of repetitions.

What are the three parts inside a for loop header, in order?

  • start, check, step
  • check, step, start
  • step, start, check
  • start, step, check

Answer: start, check, step. The header is start (e.g. $i = 1), check (e.g. $i <= 5), then step (e.g. $i++).

How does a do-while loop differ from a while loop?

  • It never runs
  • It cannot use a condition
  • It only loops over arrays
  • It always runs the body at least once

Answer: It always runs the body at least once. do-while checks the condition AFTER the body, so the body always runs at least once.

Which loop is the most-used way to walk through an array?

  • for
  • foreach
  • do-while
  • repeat

Answer: foreach. foreach hands you each element in turn with no index or off-by-one mistakes.

In foreach ($arr as $key => $value), what does the part before => give you?

  • The key
  • The value
  • The array length
  • The next item

Answer: The key. The part before => is the key; the part after is the value.

What does the continue statement do inside a loop?

  • Stops the loop completely
  • Restarts the loop from the start
  • Skips the rest of the current pass and goes to the next
  • Pauses the script

Answer: Skips the rest of the current pass and goes to the next. continue skips the rest of the current iteration and jumps to the next one.

What does break 2 do inside two nested loops?

  • Breaks only the inner loop
  • Breaks out of both loops at once
  • Skips two iterations
  • Causes an error

Answer: Breaks out of both loops at once. The number after break is how many nested loops to exit, so break 2 leaves both.

What does this print? for ($i=1; $i<=6; $i++) { if ($i % 2 === 0) continue; echo $i; }

  • 123456
  • 246
  • 1357
  • 135

Answer: 135. continue skips even numbers, so only the odd values 1, 3, 5 are printed: 135.

What usually causes an infinite loop?

  • Using foreach
  • Forgetting to change the variable the condition depends on
  • Adding a break
  • Using a for loop

Answer: Forgetting to change the variable the condition depends on. If nothing in the body moves toward the condition becoming false, the loop runs forever.

Which keyword closes a foreach written with the alternative template syntax?

  • endwhile;
  • endfor;
  • endforeach;
  • end;

Answer: endforeach;. The alternative syntax closes a foreach loop with endforeach;.

Continue this course

Frequently asked questions

When should I use foreach instead of for?

Reach for foreach almost every time you walk through an array — it's cleaner, faster to read, and you can't get the bounds wrong. Use a plain for loop only when you genuinely need a counting number for its own sake (e.g. repeat something exactly 10 times, or step backwards), or when you need to skip by more than one. For associative arrays (named keys) foreach is the only sensible choice, because the keys aren't 0, 1, 2.

What is the difference between while and do-while?

A while loop checks its condition BEFORE the first pass, so the body might run zero times. A do-while loop runs the body first and checks the condition AFTER, so it always runs at least once. Use do-while when the work must happen at least one time — for example, show a menu and then ask whether to show it again.

What do break and continue do, and what does the number after them mean?

break stops the loop entirely and carries on with the code after it. continue skips the rest of the current pass and jumps straight to the next iteration. The optional number is the number of nested loops to act on: inside two loops, break 2 leaves both loops at once, and continue 2 skips to the next pass of the outer loop. Without a number they default to 1 (the innermost loop).

Why did my array values change after a foreach loop with &$value?

When you write foreach ($arr as &$value) the & makes $value a reference — a live link to each element, so edits actually change the array. The trap is that after the loop, $value still points at the LAST element. If you reuse $value (or run another foreach over the same array) you can overwrite that last item. The fix is to call unset($value) immediately after the loop to break the link.

What is an infinite loop and how do I avoid one?

An infinite loop is a loop whose condition never becomes false, so it runs forever and hangs your script. It almost always means you forgot to change the variable the condition depends on — for example a while ($i < 10) with no $i++ inside. Always make sure something in the loop body moves you toward the condition being false: increment a counter, shrink a list, or set a flag.