for Loop
The for loop is PHP's tool for repeating a block of code a known or countable number of times. Where a while loop only tracks a condition, and a foreach loop only tracks "the next item in this array," a for loop packs three separate ideas — where to start, when to stop, and how to move forward — into a single line. That makes it the natural choice whenever the number of repetitions can be expressed as a range, a count, or a step, rather than as "until some array runs out."
The three clauses
A for statement has the shape for (initialization; condition; increment) { ... }. Each of the three clauses has a distinct job,
and PHP evaluates them in a very specific order: the initialization
runs exactly once, before the loop starts; the condition is checked
before every iteration, including the very first one; and the
increment runs after every iteration, right before the condition is
checked again.
A basic counting loop
<?php
for ($i = 1; $i <= 5; $i++) {
echo "Count: {$i}\n";
}Count: 1 Count: 2 Count: 3 Count: 4 Count: 5
$i = 1— the initialization, run once, typically used to create and set a loop counter.$i <= 5— the condition, checked before each pass; the loop keeps running as long as this is truthy.$i++— the increment, run after each pass, typically used to move the counter forward.
All three clauses are optional
None of the three clauses is actually required. You can leave any of
them empty as long as you keep the semicolons in place, and PHP will
simply skip whatever you omitted. Taken to the extreme, for (;;) { ... } is an infinite loop with no built-in exit condition at all —
you would need a break statement inside the body to escape it.
Moving parts outside the for statement
<?php
$i = 1; // initialization moved above the loop
for (; $i <= 3; $i++) {
echo "Item {$i}\n";
}
// A deliberately open-ended loop that breaks itself
$attempts = 0;
for (;;) {
$attempts++;
if ($attempts >= 3) {
break;
}
}
echo "Stopped after {$attempts} attempts\n";Item 1 Item 2 Item 3 Stopped after 3 attempts
Multiple expressions in one clause
Each clause can actually hold more than one expression, separated by commas. This is most often used to initialize or update two related counters in lockstep, without needing a separate variable declared outside the loop. Only the last expression in the condition clause is checked as the loop's stopping test — PHP still evaluates all of them, but only the final one's truthiness decides whether the loop continues.
Two counters moving in opposite directions
<?php
for ($low = 0, $high = 10; $low < $high; $low++, $high--) {
echo "low={$low} high={$high}\n";
}low=0 high=10 low=1 high=9 low=2 high=8 low=3 high=7 low=4 high=6
Nested for loops
A for loop can contain another for loop, which is how you build anything grid-shaped: multiplication tables, calendars, board patterns, or coordinate scans. The outer loop controls the rows and the inner loop controls the columns; the inner loop runs completely, for every single pass of the outer loop.
A small multiplication table
<?php
for ($row = 1; $row <= 3; $row++) {
for ($col = 1; $col <= 3; $col++) {
echo str_pad((string) ($row * $col), 4, ' ', STR_PAD_LEFT);
}
echo "\n";
}1 2 3 2 4 6 3 6 9
The same nesting pattern draws shapes instead of numbers. Here the outer loop picks the row, and the inner loop prints one * per column, growing wider on each row:
A simple triangle pattern
<?php
for ($row = 1; $row <= 4; $row++) {
for ($col = 1; $col <= $row; $col++) {
echo '*';
}
echo "\n";
}* ** *** ****
Stepping by something other than 1
Because the increment clause can be any expression, a for loop handles ranges that skip values just as naturally as it handles simple counting. This is one of the clearest cases where for outperforms foreach: there is no array to iterate over, only a mathematical sequence.
Every third number, and counting backward
<?php
for ($i = 0; $i <= 15; $i += 3) {
echo "{$i} ";
}
echo "\n";
for ($i = 10; $i >= 0; $i -= 2) {
echo "{$i} ";
}
echo "\n";0 3 6 9 12 15 10 8 6 4 2 0
for vs foreach for iterating arrays
It is entirely possible to walk an array with a for loop, indexing in manually with $array[$i]. It is also, in most cases, the wrong choice. Manual indexing assumes the array has sequential integer keys starting at zero, which breaks silently the moment a key is removed, the array is filtered, or the array uses string keys at all. A foreach loop reads whatever keys and values actually exist, so it cannot go out of bounds and does not care how the array is keyed.
Fragile indexing vs foreach
<?php
$fruits = ['apple', 'banana', 'cherry'];
unset($fruits[1]); // gap left at index 1
// for loop: silently skips or errors on the gap
for ($i = 0; $i < count($fruits); $i++) {
echo ($fruits[$i] ?? '(missing)') . "\n";
}
// foreach: only ever visits keys that really exist
foreach ($fruits as $index => $fruit) {
echo "{$index} => {$fruit}\n";
}apple (missing) cherry 0 => apple 2 => cherry
for still earns its place when you genuinely need the index for arithmetic — comparing an element to its neighbor, walking two arrays in parallel by position, or processing every second element — or when you are counting through a numeric range that was never an array to begin with. If the task is simply "do something with each value in this array," reach for foreach; it is shorter, cannot misalign with the array's real keys, and communicates intent more clearly to anyone reading the code later.