arrays are certainly useful for reference or storage but a significant portion of their application in the real world comes from being able to do something to every item inside. that's where foreach shows up.
$food = ["soup", "salad", "apple pie", "tortillas", "gummy bears"];
foreach ($food as $item) {
print_r("do you like eating " . $item . "?\n");
}
returns...
do you like eating soup?
do you like eating salad?
do you like eating apple pie?
do you like eating tortillas?
do you like eating gummy bears?
note the extra new line at the end because each print_r ends with \n.
there is a shortcut to writing foreach to perform repeated tasks like this but it has some significant limitations. it is often simpler for basic tasks, though -- array_map. the same code looks like this...
$food = ["soup", "salad", "apple pie", "tortillas", "gummy bears"];
array_map(fn($item) => print_r("do you like eating " . $item . "?\n"), $food);
in other words, perform the action after => on each item in array $food using $item as the placeholder.
foreach can do more than just treat each item as an individual piece. it can keep track of how it is referenced inside the array by splitting its key and its value into two linked pieces.
$animals = ["dog" => "puppy", "cat" => "kitten", "horse" => "foal", "cow" => "calf", "deer" => "fawn", "pig" => "piglet"];
foreach ($animals as $adult => $child) {
print_r("a baby " . $adult . " is called a " . $child . ".\n");
}
returns
a baby dog is called a puppy.
a baby cat is called a kitten.
a baby horse is called a foal.
a baby cow is called a calf.
a baby deer is called a fawn.
a baby pig is called a piglet.
we can use what we've already learned to avoid potential problems with vowels like this...
$bigAnimals = ["lion", "leopard", "elephant", "rhino", "buffalo", "giraffe", "zebra", "aardvark"];
foreach ($bigAnimals as $animal) {
$animal = in_array($animal[0], ["a", "e", "i", "o", "u"]) ? "an " . $animal : "a " . $animal;
print_r("have you ever seen " . $animal . "?\n");
}
returns
have you ever seen a lion?
have you ever seen a leopard?
have you ever seen an elephant?
have you ever seen a rhino?
have you ever seen a buffalo?
have you ever seen a giraffe?
have you ever seen a zebra?
have you ever seen an aardvark?
in other words, if the first character in each $animal is one of the vowels in the array ["a", "e", "i", "o", "u"], save an plus the original value of $animal to $animal. otherwise, do it with a .
for allows us to do a task multiple times.
for ($i = 0; $i <= 5; $i++) {
print_r("i have done this loop " . $i . " times.\n");
}
returns...
i have done this loop 0 times.
i have done this loop 1 times.
i have done this loop 2 times.
i have done this loop 3 times.
i have done this loop 4 times.
i have done this loop 5 times.
you have already seen ++ used to add one to a variable and <= used to compare numbers. because the number of times the loop runs is called the index, it is conventional to use $i unless the name of the variable is important so you will often see that as a name in the wild. the syntax for for is the initial value, the condition to continue for another loop then the action to perform on the index variable each loop. in this case, we start with $i being 0, check to make sure $i <= 5, do the contents between {} and add 1 to $i before checking again and potentially doing the contents again.
this is also an alternative method for performing a task on each item in an array, using things you have already seen.
$food = ["soup", "salad", "apple pie", "tortillas", "gummy bears"];
for ($i = 0; $i < count($food); $i++) {
print_r("do you like eating " . $food[$i] . "?\n");
}
returns...
do you like eating soup?
do you like eating salad?
do you like eating apple pie?
do you like eating tortillas?
do you like eating gummy bears?
just like in the earlier example with foreach. when you can, foreach is often easier to read and understand but for can be useful when foreach doesn't fit the particular needs of the moment.
it is often necessary to monitor a variable that is changing and act on that condition. the typical use is when a variable is being changed somewhere else -- like a file on the web server being modified or an external component receiving information. but, for understanding, we can modify it ourselves.
$i = rand(1, 10);
while ($i != 10) {
print_r($i . " is not ten.\n");
$i = rand(1, 10);
}
print_r($i . " is finally ten!");
if $i is any number other than 10, the loop runs and tells us it's not 10. when the loop has finished its last run, it tells us we've finally reached 10. a sample return is...
5 is not ten.
4 is not ten.
5 is not ten.
1 is not ten.
4 is not ten.
4 is not ten.
6 is not ten.
1 is not ten.
9 is not ten.
1 is not ten.
10 is finally ten!
note that the loop might never run. if $i is 10 on the first line, the condition $i != 10 is never true so the loop is skipped.
if you want to guarantee your loop running at least once, there is another option, do.
$i = 2;
do {
print_r("i wonder if there are " . $i . " mice in the field.\n");
$i++;
} while ($i < 5);
returns...
i wonder if there are 2 mice in the field.
i wonder if there are 3 mice in the field.
i wonder if there are 4 mice in the field.
if we change $i to 10 in the first line, it returns...
i wonder if there are 10 mice in the field.
despite the condition not being met, the loop runs the first time because we haven't gotten to the check for the condition yet.
this can be useful if, for example, you are attempting to remove a file. you tell it to remove the file then, if the file still exists, loop back and do it again until it's gone. you guarantee at least one attempt before checking. if you want to check whether the file still exists before attempting to delete it, you can use while without do.
you have already seen break used when we talked about switch. it also works inside foreach, for and while loops (including those beginning with do). it allows you to check for something happening and exiting a loop even if the loop condition still isn't true.
$rooms = ["bedroom", "bathroom", "kitchen", "", "den", "dining room"];
foreach ($rooms as $room) {
print_r("are your keys in the " . $room . "?\n");
}
returns...
are your keys in the bedroom?
are your keys in the bathroom?
are your keys in the kitchen?
are your keys in the ?
are your keys in the den?
are your keys in the dining room?
we already know how to skip the empty element in the array but, if we want to simply stop altogether if there's an empty element, we can do that with break.
$rooms = ["bedroom", "bathroom", "kitchen", "", "den", "dining room"];
foreach ($rooms as $room) {
if (!strlen($room)) {
break;
}
print_r("are your keys in the " . $room . "?\n");
}
returns...
are your keys in the bedroom?
are your keys in the bathroom?
are your keys in the kitchen?
strlen returns the length of a string. if the length of the string is 0, it is equivalent to false and the if block runs, exiting the foreach without actually finishing the whole array.
a typical use case for break when looping through an array is, if you're looking for a particular result from each item, once you've found it, there's no point in wasting time checking every remaining item. so you can skip the rest with break.
the opposite of break is continue. if you want to skip to the next repetition without finishing the one you're in, just add continue. we can do it with the same example.
$rooms = ["bedroom", "bathroom", "kitchen", "", "den", "dining room"];
foreach ($rooms as $room) {
if (!strlen($room)) {
continue;
}
print_r("are your keys in the " . $room . "?\n");
}
returns...
are your keys in the bedroom?
are your keys in the bathroom?
are your keys in the kitchen?
are your keys in the den?
are your keys in the dining room?
when the length of the string is 0, it doesn't run the rest of the loop. it just skips to the next one.