Subscribe to PHP Freaks RSS

PHP Loops

Print
by Crayon Violent on Jun 19, 2008 2:46:30 PM - 85,066 views

What is a Loop?

Looping is simply a way for you to reduce the amount of code and/or content you have to write out. The idea is that you have something you have to do, or some content you have to show, and instead of just "writing it all out," you find a pattern to it - a common denominator - and let PHP execute the code or generate the content piece by piece using that pattern, based on a condition.

A condition is a way of letting PHP know how many times to run your loop, or when to stop running your loop. The ability to take a condition and execute a set of instructions over and over as long as that condition is true is one of the basic cornerstones of programming.

To demonstrate how loops work, we will use a "for" loop to solve the following example problem:

"Joe wants to be able to take a range of numbers and find out how many numbers are divisible by a certain number, within that range of numbers. "

The Code

Okay the first thing I am going to do is give you the complete script for the solution to this problem. That way, you have the goods right up front and can refer to it as a whole.

<?php

// variable to hold form
$form = <<<SOMEFORM
<form action = '{$_SERVER['PHP_SELF']}' method = 'post'>
   Range Start: <input type = 'text' name = 'start' size = '3'><br />
   Range Finish: <input type = 'text' name = 'finish' size = '3'><br />
   Divided By: <input type = 'text' name = 'num' size = '3'><br />
   <input type = 'submit' value = 'Find Numbers'>
</form>
SOMEFORM;

// if we have posted info...
if ($_POST) {
   // assign post vars to reg vars for easier handling
   $start = (int) $_POST['start'];
   $finish = (int) $_POST['finish'];
   $num = (int) $_POST['num'];

   echo "The following numbers from $start to $finish are divisible by $num : <br />";
   // loop from $start to $finish, 1 number at a time
   for ($x = $start; $x <= $finish; $x++) {
      // if the modulus of the current number and the divided by number
      // is zero, then it is evenly divisible by that number
      if (($x % $num) == 0) {
         // echo the number
         echo "$x ";
      } // end if
   } // end for
} // end if

// echo out the form
echo $form;

?>

What We Care About

There may be a lot of things in that script you may be unfamiliar with. Basically there's a form so we can get input from the user, and that's about it. The only part of the script we are really going to focus on is this part:

// loop from $start to $finish, 1 number at a time
   for ($x = $start; $x <= $finish; $x++) {
      // if the modulus of the current number and the divided by number
      // is zero, then it is evenly divisible by that number
      if (($x % $num) == 0) {
         // echo the number
         echo "$x ";
      } // end if
   } // end for

Let's Get Loopy

All loops are broken down into four basic pieces:

- The initialization
- The condition
- The instruction
- The iteration

A basic "for" loop looks like this:


for (initialization; condition; iteration) {
instruction
}

We start out with telling PHP what kind of loop it is. Since it is a "for" loop, we start out by simply saying "for ..." The initialization, condition, and iteration are put inside the ( )'s, separated by a semicolon. We use { } brackets to show where the start and end of our instruction is. Some people like to put the { on its own line like this:


for (initialization; condition; iteration)
{
instruction
}

It's really just a matter of style; PHP doesn't care either way.

Going Around In Circles

The Initialization
This is where the loop starts. We tell the "for" loop where to start by assigning the starting number to a variable $x. In this example, our starting number is represented by $start - what the user puts in from the form.

In a "for" loop, the initialization must always be a number. It doesn't have to be a whole number, or even positive, but it has to be a number, and it has to be initialized by assignment to a variable, so that PHP can keep track of counting each iteration of the loop. In other words, it has to have this basic format:

$x = $start;

The Condition
This is where we control how many times we want the loop to repeat, or iterate. A "for" loop counts from one number to some other number. This is where we tell PHP what that other number is. Without the condition, the loop will never stop repeating, and we would have what's called an infinite loop.

The condition must always check the initializing variable against a number value. It doesn't have to be a whole number, it can be positive or negative, but it has to be a number value. You can use any of the normal condition operators for the condition. Some basic formats (that are relevant to our example) for the condition are:
$x < $finish;
$x <= $finish;
$x != $finish;

...And Again And Again

The Iteration
This is where PHP increments the initialization variable. In our example, we do $x++. This is just a shorthand way of doing $x = $x + 1, which is equally valid. it is also equally valid to increment it by something other than 1. It doesn't even have to be a whole number. It can even subtract a number so your loop can "count down."

How you want your loop to count (the increments per loop, counting up or down, etc..) is entirely up to you, and you will base that on what your goal for the instruction is. In this example, we could just as easily start with the ending number and count down to the starting number, subtracting 1 from $x during each iteration of the loop, like so:

for ($x = $finish; $x >= $start; $x--) {
      if (($x % $num) == 0) {
         echo "$x ";
      } // end if
   } // end for

On that note, be careful to "phrase" your loop correctly, or you will not get your desired results, or worse, end up with an infinite loop. Consider this loop:

$start = 100;
$finish = 200;

for ($x = $start; $x >= $finish; $x++) {
   echo "$x ";
} // end for

We are telling the loop to start at 100, and while $x is greater than 200, run the instruction. Well the problem is, right out the gate, the condition is false, because 100 is not greater than 200. Our loop will never execute. Or how about this example:

$start = 100;
$finish = 200;

for ($x = $finish; $x >= $start; $x++) {
   echo "$x ";
} // end for

Whoops, we accidentally put the start and finish variables backward. Since we start at 200, our loop will keep iterating as long as it is greater than 100. Each iteration, we add 1 to 200, so the condition will always evaluate as true. The loop will never stop, thus creating an infinite loop.

Show Me The Money!

The Instruction
The Instruction is what you want PHP to do each iteration of your loop. It can be something as simple as echoing out the current iteration, doing some math based on each iteration, or pulling out a new row of information from a database. This is the "pattern," or "common denominator" to your large chunk of code/content. It's the individual brick that your loop stacks over and over to make your wall.

The most challenging part of making a loop is the Instruction part. Finding the pattern isn't always so easy as our simple condition to test if a number divides evenly by another number. You can use virtually anything inside your loop to build your pattern, from regular assignments/outputs to conditions; you can even put another loop inside your loop! And there's really no limit to how far you can "nest" things inside one another, except for how far you can wrap your head around the logic. Finding a pattern to make a loop out of deserves it's own tutorial altogether. It is what makes looping an artform.

Raspberry Red, Lemony Lemon, Orangey Orange!

Tucan Sam isn't the only dude offering different kinds of loops. PHP offers four different ways to reiterate pieces of code:

- The while loop
- The do...while loop
- The for loop
- The foreach loop

In principle, each kind of loop has the same basic components and does the same basic thing, but their nuances make it possible to write your code more efficiently, depending on your circumstance. The nuances in the loops are being able to put the loop's components in different orders, or even combining components of the loop.

Changing the order of the components is important to know, because this can and will change the outcome of your loop. For example, some loops or orders will execute the instruction first, then check the condition, so you will always get at least one iteration of the loop.

The While Loop

The basic While loop syntax looks like this:


initialization
while (condition) {
instruction
iteration
}

A working example might look like this:

$x = 0;
while ($x < 10) {
   echo "$x ";
   $x++;
}

In essence, this while loop is exactly like a for loop. It has a set initializer, a set condition, and a set iteration. You are, of course, free to switch the order of the instruction and the iteration. In this example, it would actually be better to write this as a for loop, because that's what the for loop was made for.

The power of a while loop is being able to combine the initializer and even sometimes the iteration with the condition. One scenario in which this comes in handy is if you have a list of information in a database and you want to grab that information and make a loop to display that data, but you aren't sure how many iterations there will be, because you aren't sure how many rows will be returned from the database.

Example:

$sql = "select name from table";
$result = mysql_query($sql);
while ($name = mysql_fetch_assoc($result)) {
   echo "{$name['name']} <br />";
}

In this example, we run a query to select all the names in a table in your database. Inside the ( ...), all 3 components (initialization, condition, iteration) are combined into a single expression.

The initialization is easy enough to spot: $name = ... is the initialization.

mysql_fetch_assoc is a special function that grabs a name from the result source of the query and then internally increments the pointer of that result source to the next name in the results. This is the iteration, because when the loop finishes and goes back to the beginning, it will have a new name to fetch.

The condition comes into play by the act of being able to initialize $name to the next name in the result source. If mysql_fetch_assoc gets to the end of the list of names, it will return false, so the next time the loop tries to assign a name to $name, it will fail, thus ending the loop.

The Do...While Loop

The do..while loop works pretty much exactly the same as the while loop, except that the instruction will always be executed first. The basic syntax looks like this:


initialization
do {
instruction
iteration
} while (condition);

As with the while loop, putting the components in those positions makes it a glorified for loop, and you should use a for loop. Just like the while loop, the power is being able to combine the components and/or make a loop with an undetermined amount of iterations.

If we were to use a do...while loop with the previous database example :

$sql = "select name from table";
$result = mysql_query($sql);
do { 
   echo "{$name['name']} <br />";
} while ($name = mysql_fetch_assoc($result));

In this example, we're going to run into some problems. Because the instruction comes first, $name['name'] does not exist until after the first iteration of the loop. In my experience, there aren't very many circumstances where a do...while loop is preferred over a while loop. It's really only good for wanting to make a loop where you want the instruction to be executed at least one time, no matter what.

The For Loop

We used the for loop in our example on how loops work, so you should already have a decent understanding about this loop. The only thing to really understand about the for loop, is that it is the "strictest" loop out of the bunch. It needs a set starting point, and a set ending point. It's useful if you know exactly how many iterations you are dealing with, simple as counting from 1 to 10.

As shown previously:


for (initialization; condition; iteration) {
instruction
}

The condition will always be evaluated before the instruction is complete, and the instruction will be executed before the value is iterated.

initialization -> condition -> instruction -> iteration -> condition -> instruction -> iteration ...

The Foreach Loop

A foreach loop is specially designed for working with array elements. A basic structure of a foreach loop looks like this:


foreach ($array as $value) {
instruction
}

In this loop, the $value is the initialization component. The condition and iteration comes from the $array. The $array represents an array. The loop starts an internal pointer at the beginning of the array, and assigns the value of that element to $value, and then executes the instructions. When the instructions are done, the pointer is moved to the next element of $array (the iteration). If there is no element (the end of the array), the condition evaluates false, and the loop ends.

Consider this example:

$letters = array('a','b','c');

foreach($letters as $letter) {
   echo "$letter <br />";
}

The foreach loop points to the first element of the $letters array, executes the instructions, moves to the next element, etc... and when it runs out of elements, the loop is over. The output would be:

a
b
c

The foreach loop accommodates associative arrays, as well. An associative array is an array that assigns a "name" to the element, or key, of the array. Example:

$account = array('name' => 'John', 'number' => 123, 'age' =>30);

foreach($account as $key => $val) {
   echo "$key : $val <br />";
}

The output of this would be:

name : John
number : 123
age : 30

Continue and Break

PHP offers two language constructs to break out of your loop: continue and break. "Continue" is used to skip the rest of the instructions in the current iteration of the loop. Let's say you want to count from 1 to 100 but skip printing all the even numbers:

for ($x = 0; $x <= 100; $x++) {
   if (($x % 2) == 0) { 
      continue;
   }
   echo "$x <br />";
}

Each iteration of the loop we have a condition to check if $x is evenly divisible by 2. If it is, we skip echoing out $x and move on to the next iteration. Now we could have just as easily done this:

for ($x = 1; $x <= 100; $x = $x + 2) {
   echo "$x <br />";
}

But that's not the point! Besides, continue and break are useful for things much more complex than this. Break works the same way as continue, except that it breaks out of the whole loop, instead of the current iteration.

Both break and continue can take an optional argument for you to specify what level loop to break or continue. This is useful for nested loops, where if you for example have a loop running inside another loop and if some condition is met, you want to exit out of the loop, even the main loop, you can do this:

for ($x = 0; $x <= 10; $x++) {
   for ($y = $x; $y <= 10; $y++) {
      $z = $x * $y;
      echo "$x * $y = $z <br />";
      if ($z == 50) { 
         break(2);
      }
   }
}

In this nested loop, we are printing out everything from 1 * 1 to 10 * 10 but we have a condition inside the nested loop to break out of all of the loops if we find an answer that equals 50.

That's All Folks!

Well, that's about all there is to know about loops. The basic syntax of loops is pretty easy to figure out; it's finding the patterns to loop that's the tough part. I hope that this has helped some of you out there who are just getting started and want to know what's the point of loops and why are there different kinds. Perhaps in a future tutorial I will attempt to tackle tips and tricks to finding patterns for loop instructions.

Until then, happy coding!

Crayon Violent

Comments

Ben Smithers Jun 20, 2008 5:07:40 AM

Again, very nice CV. Only thing i would mention is that it's not strictly true that a for loop requires all 3 parameters. This is a perfectly valid for loop:

<?php
for($x=0;;){
}
?>

As is this:

<?php
for(;$x<5;){
}
?>

Of course, they serve no real useful purprose (use a while loop, it's easier to follow) but i had to find something wrong with it :P

Crayon Violent Jun 20, 2008 10:19:46 AM

Ah you are right, but in order for the loops to function properly, they still need to have all the components somewhere. Your first example, while syntactically correct, would in and of itself be an infinite loop. Using your first example, you would have to put the condition and iteration inside the instruction. Example:

<?php  
for($x=0;;) {  
   if ($x > 10) break;
   $x++;
}

I'm glad you pointed that out though : )

kahratka Jun 20, 2008 10:32:40 AM

A concise explanation of loops. Very good.

floyd0987 Feb 26, 2010 4:08:04 PM

I tried the foreach loop to extract data from a recordset but i only get the first record. how come?

Crayon Violent Feb 27, 2010 6:23:52 PM

Please post your problem on the forums. Also, be sure to include details about your problem. Nobody will be able to help you if you do not provide more information about your problem (such as posting the relevant code).

marginhound Sep 11, 2012 9:22:05 PM

Very nice tutorial -

Once folks are comfortable with these concepts, recommend they check out the array functions (array_map, array_filter, array_reduce). This allows you to simplify loops against an array using a standard function (core PHP or user defined) and express the loop as a single line of code. This is helpful if you are repeatedly executing similar operations against multiple lists.

This becomes even more powerful now that we have closures in PHP 5.3; you can dynamically create functions (takes some practice, but really powerful once you master it) and apply them to your arrays... I used to build an HTML generator.

Code sample from the docs at php.net:

$func = function($value) {
return $value * 2;
};

print_r(array_map($func, range(1, 5)));

Add Comment

Login or register to post a comment.