Implicit Evaluation with PHP

18 January 2007

Loops in PHP

PHP gives programmers many varieties of loops to work with. Despite an overwhelming selection, each is tailored, really, to just one scenario.


Foreach

Foreach is the youngest of computer science’s loops. Given an array, it will iterate over each of the arrays values (and optionally, keys).

Syntax foreach ($array as [$key => ] $value) { }
Sample foreach (array ("introduction", "body", "conclusion") as $part) { }
Sample foreach ($dataset as $ixKey => $row) { }

Foreach often gives you the same result with cleaner code, then it’s older brother For.

For

For has the intense disadvantage of having the most complex syntax of any looping mechanism. However its high level of configurability allows for to be used for both iterating over an array (like foreach) as well as generating data.

Syntax for (STARTING_VALUE; CONTINUE_CONDITION; UPDATE_OPERATION) { }
Sample for ($ixKey = 0; $ixKey < 10; ++$ixKey) { … }
Sample for ($ixName = 0; $ixName < strlen ("Bob Smith"); ++$ixName) { ... }
Sample for ($intMonth = 1; $intMonth < = 12; ++$intMonth) { ... }

For is best used within fixed bounds. Where foreach will loop over the entirety of an array, for could allow you to loop over the indices of a subset of an array. The added code in a for loop if often wasted for simple operations but more concise than using a simpler loop and tracking other parameters manually.

While

While is the most basic of all loops. It can easily implement almost any other loop because it just doesn’t do that much. While is often used to dynamically fetch stream results, be it from a database (most commonly) or files/sockets. In this since, it is similar to foreach, except, foreach operates on arrays of a defined size whereas while operates on conditions. In use, the programmer usually does not inherently know the bounds of the data in operation when either a foreach or while loop is being used.

Syntax while (CONTINUE_CONDITION) { … }
Sample while ($result = mysql_fetch_assoc ($resultset)) { ... }
Sample while (!feof ($fp)) { ... }

The first sample might surprise you. Its not doing a comparison, you might notice, it’s doing an assignment. However, there is an implicit truth comparison based on the result. If zero/null/empty string is the value being assigned, the truth statement will be false, hence an end-condition for a loop. This actually happens on all conditions, however, when you are returning a boolean value, you will not think about the languages implicit (TRUE != FALSE) comparison.

Do

The do loop is only a slightly modified version of the while loop. In while, the loops contents are executed so long as the loops condition holds true. In a do loop, the contents are executed regardless and then the loop is repeated so long as the condition is true. A do loop will therefore always run at least one iteration while other loops may fail before even their first iteration. In practice, do is rarely used as it is more suited to interactive applications (such as text-based terminal applications).

Syntax do { … } while (CONTINUE_CONDITION);

In other languages or settings, do may be more appropriate than while, but on the web, every use of do I’ve seen can be more elegantly handled in a while loop.

Do has seen a bit of a resurgence with exception-based languages. In languages supporting the Try/Catch paradigm, a do loop often surrounds the code with a final break instruction within the try block. This allows normal code to execute and exit cleanly while giving error-producing code to try again. Of course, improper use of this can lead to infinite loops which will crash your application. PHP does support try/catch as of version 5.0 so perhaps over the next few years, do will become more used in PHP.

Goto

High level languages like PHP are ultimately expressed in assembler when running on popular CPUs. Assembler does not have any loop construct, but does have a “GOTO” instruction to resume execution at a particular memory address. Over the first few decades of the computer science, GOTO was often used also in high level languages for high-preformance loops. Simultaneous rampant misuse of goto lead to the phenomenon known as spaghetti-code. PHP, to its credit, has not featured this construct but is slated to add support for a variation of goto in PHP version 6.0.

One of the problems of implementing goto in modern garbage-collected languages is that goto permits completely changing lexical scopes in one instruction. The compiler is left not knowing whether to clean up the variables in the old scope or not. PHP’s solution to this is to not allow arbitrary goto calls, but instead, add functionality to the break instruction. Break, of course, steps out of the lexical scope. Normally, the break call will advance execution to the appropriate “}” in code. PHP6 will allow break-ing to a named label. By restricting the scope the break can fall to, garbage collection remains possible. Make no mistake, it is still a goto, however by not using that term, developers won’t expect goto’s full functionality.

Recursion

Recursion can be a loop. Any tail-recursive function can be implemented directly with these other constructs, but nearly all instances of any recursion can be considered a loop. The major difference between looping with recursion is that there is no explicit continue/stop line. There is an implicit one, though, and that is the call to itself. At some point a recursive function knows its done, and that is the continue condition. Since this is a feature enabled by the language, not a constructed provided by the language, there is no standard way to illustrate this besides with a sample and a disclaimer that all uses can potentially differ.

Sample function fib ($num) {
if ($num < 2) {
return $num; /* continue? false */
} else {
return fib($num - 1) + fib ($n - 2); /* continue? true */
}

One Comment currently posted.

Nick says:

Hello:

I think that you can add:

array_map(); array_walk(); and array_walk_recursive();

To your loops in PHP. As I don’t think that many people realize that you can do quite powerful things very quickly across arrays with these constructs. (kinda like a real tight foreach loop)

Nick

Post a comment on this entry: