while tests before each pass and do-while after, so its body runs at least once. A for loop keeps a counter's start, test and step on one line, each allowing comma-separated expressions, and foreach walks any array or Traversable, optionally with keys and destructuring.
<?php
$i = 0;
while ($i < 3) { echo $i++; } // tests before each pass
do { echo $i; } while ($i < 3); // runs once although $i is already 3
for ($j = 0, $sum = 0; $j < 10; $j++) { $sum += $j; }
echo " | sum $sum\n";
foreach (['ISBN-1' => 4, 'ISBN-2' => 0] as $isbn => $qty) { echo "$isbn:$qty "; }
foreach ([[101, 'paid'], [102, 'shipped']] as [$id, $status]) { echo "#$id $status "; }
echo "\n";
$prices = [10, 20, 30];
foreach ($prices as &$p) { $p *= 2; } // by reference: edits the array in place
foreach ($prices as $p) {} // $p still refers to $prices[2]
echo implode(", ", $prices), "\n"; // so the last element was overwrittenOutput
0123 | sum 45 ISBN-1:4 ISBN-2:0 #101 paid #102 shipped 20, 40, 40
After a by-reference foreach, $p stays bound to the last element, and the second loop writes each value into it. Put unset($p); straight after such a loop, or use array_map() (map, filter, walk).