Control Structures

Any PHP script is built out of a series of statements. A statement can be an assignment, a function call, a loop, a conditional statement of even a statement that does nothing (an empty statement). Statements usually end with a semicolon. In addition, statements can be grouped into a statement-group by encapsulating a group of statements with curly braces. A statement-group is a statement by itself as well. The various statement types are described in this chapter.

if

The if construct is one of the most important features of many languages, PHP included. It allows for conditional execution of code fragments. PHP features an if structure that is similar to that of C:

 if (expr)
     statement
 

As described in the section about expressions, expr is evaluated to its truth value. If expr evaluates to TRUE, PHP will execute statement, and if it evaluates to FALSE - it'll ignore it.

The following example would display a is bigger than b if $a is bigger than $b:

 if ($a > $b)
     print "a is bigger than b";
 

Often you'd want to have more than one statement to be executed conditionally. Of course, there's no need to wrap each statement with an if clause. Instead, you can group several statements into a statement group. For example, this code would display a is bigger than b if $a is bigger than $b, and would then assign the value of $a into $b:

 if ($a > $b) {
     print "a is bigger than b";
     $b = $a;
 }
 

If statements can be nested indefinitely within other if statements, which provides you with complete flexibility for conditional execution of the various parts of your program.

else

Often you'd want to execute a statement if a certain condition is met, and a different statement if the condition is not met. This is what else is for. else extends an if statement to execute a statement in case the expression in the if statement evaluates to FALSE. For example, the following code would display a is bigger than b if $a is bigger than $b, and a is NOT bigger than b otherwise:

 if ($a > $b) {
     print "a is bigger than b";
 } else {
     print "a is NOT bigger than b";
 }
      

The else statement is only executed if the if expression evaluated to FALSE, and if there were any elseif expressions - only if they evaluated to FALSE as well (see below).

elseif

elseif, as its name suggests, is a combination of if and else. Like else, it extends an if statement to execute a different statement in case the original if expression evaluates to FALSE. However, unlike else, it will execute that alternative expression only if the elseif conditional expression evaluates to TRUE. For example, the following code would display a is bigger than b, a equal to b or a is smaller than b:

 if ($a > $b) {
     print "a is bigger than b";
 } elseif ($a == $b) {
     print "a is equal to b";
 } else {
     print "a is smaller than b";
 }
      

There may be several elseifs within the same if statement. The first elseif expression (if any) that evaluates to true would be executed. In PHP, you can also write 'else if' (in two words) and the behavior would be identical to the one of 'elseif' (in a single word). The syntactic meaning is slightly different (if you're familiar with C, this is the same behavior) but the bottom line is that both would result in exactly the same behavior.

The elseif statement is only executed if the preceding if expression and any preceding elseif expressions evaluated to FALSE, and the current elseif expression evaluated to TRUE.

Alternative syntax for if structures: if(): ... endif;

PHP offers a different way to group statements within an if statement. This is most commonly used when you nest HTML blocks inside if statements, but can be used anywhere. Instead of using curly braces, if (expr) should be followed by a colon, the list of one or more statements, and end with endif;. Consider the following example:

 <?php if ($a==5): ?>
 A = 5
 <?php endif; ?>
       

In the above example, the HTML block "A = 5" is nested within an if statement written in the alternative syntax. The HTML block would be displayed only if $a is equal to 5.

The alternative syntax applies to else and elseif as well. The following is an if structure with elseif and else in the alternative format:

 if ($a == 5):
     print "a equals 5";
     print "...";
 elseif ($a == 6):
     print "a equals 6";
     print "!!!";
 else:
     print "a is neither 5 nor 6";
 endif;
       

while

while loops are the simplest type of loop in PHP. They behave just like their C counterparts. The basic form of a while statement is:

 while (expr) statement
      

The meaning of a while statement is simple. It tells PHP to execute the nested statement(s) repeatedly, as long as the while expression evaluates to TRUE. The value of the expression is checked each time at the beginning of the loop, so even if this value changes during the execution of the nested statement(s), execution will not stop until the end of the iteration (each time PHP runs the statements in the loop is one iteration). Sometimes, if the while expression evaluates to FALSE from the very beginning, the nested statement(s) won't even be run once.

Like with the if statement, you can group multiple statements within the same while loop by surrounding a group of statements with curly braces, or by using the alternate syntax:

     while (expr): statement ... endwhile;
 

The following examples are identical, and both print numbers from 1 to 10:

 /* example 1 */
 
 $i = 1;
 while ($i <= 10) {
     print $i++;  /* the printed value would be
                     $i before the increment
                     (post-increment) */
 }
 
 /* example 2 */
 
 $i = 1;
 while ($i <= 10):
     print $i;
     $i++;
 endwhile;
      

do..while

do..while loops are very similar to while loops, except the truth expression is checked at the end of each iteration instead of in the beginning. The main difference from regular while loops is that the first iteration of a do..while loop is guarenteed to run (the truth expression is only checked at the end of the iteration), whereas it's may not necessarily run with a regular while loop (the truth expression is checked at the beginning of each iteration, if it evaluates to FALSE right from the beginning, the loop execution would end immediately).

There is just one syntax for do..while loops:

 $i = 0;
 do {
     print $i;
 } while ($i>0);
      

The above loop would run one time exactly, since after the first iteration, when truth expression is checked, it evaluates to FALSE ($i is not bigger than 0) and the loop execution ends.

Advanced C users may be familiar with a different usage of the do..while loop, to allow stopping execution in the middle of code blocks, by encapsulating them with do..while(0), and using the break statement. The following code fragment demonstrates this:

 do {
     if ($i < 5) {
         print "i is not big enough";
         break;
     }
     $i *= $factor;
     if ($i < $minimum_limit) {
         break;
     }
     print "i is ok";
     ...process i...
 } while(0);
      

Don't worry if you don't understand this right away or at all. You can code scripts and even powerful scripts without using this `feature'.

for

for loops are the most complex loops in PHP. They behave like their C counterparts. The syntax of a for loop is:

for (expr1; expr2; expr3) statement
      

The first expression (expr1) is evaluated (executed) once unconditionally at the beginning of the loop.

In the beginning of each iteration, expr2 is evaluated. If it evaluates to TRUE, the loop continues and the nested statement(s) are executed. If it evaluates to FALSE, the execution of the loop ends.

At the end of each iteration, expr3 is evaluated (executed).

Each of the expressions can be empty. expr2 being empty means the loop should be run indefinitely (PHP implicitly considers it as TRUE, like C). This may not be as useless as you might think, since often you'd want to end the loop using a conditional break statement instead of using the for truth expression.

Consider the following examples. All of them display numbers from 1 to 10:

 /* example 1 */
 
 for ($i = 1; $i <= 10; $i++) {
     print $i;
 }
 
 /* example 2 */
 
 for ($i = 1;;$i++) {
     if ($i > 10) {
         break;
     }
     print $i;
 }
 
 /* example 3 */
 
 $i = 1;
 for (;;) {
     if ($i > 10) {
         break;
     }
     print $i;
     $i++;
 }
 
 /* example 4 */
 
 for ($i = 1; $i <= 10; print $i, $i++) ;
      

Of course, the first example appears to be the nicest one (or perhaps the fourth), but you may find that being able to use empty expressions in for loops comes in handy in many occasions.

PHP also supports the alternate "colon syntax" for for loops.

 for (expr1; expr2; expr3): statement; ...; endfor;
      

Other languages have a foreach statement to traverse an array or hash. PHP uses the while statement and the list() and each() functions for this. See the documentation for these functions for an example.

break

break breaks out of the current looping construct.

 $i = 0;
 while ($i < 10) {
     if ($arr[$i] == "stop") {
         break;
     }
     $i++;
 }
      

continue

continue jumps to the beginning of enclosing the looping construct.

 while (list($key,$value) = each($arr)) {
     if ($key % 2) { // skip even members
         continue;
     }
     do_something_odd ($value);
 }
      

switch

The switch statement is similar to a series of IF statements on the same expression. In many occasions, you may want to compare the same variable (or expression) with many different values, and execute a different piece of code depending on which value it equals to. This is exactly what the switch statement is for.

The following two examples are two different ways to write the same thing, one using a series of if statements, and the other using the switch statement:

 /* example 1 */
 
 if ($i == 0) {
     print "i equals 0";
 }
 if ($i == 1) {
     print "i equals 1";
 }
 if ($i == 2) {
     print "i equals 2";
 }
 
 /* example 2 */
 
 switch ($i) {
     case 0:
         print "i equals 0";
         break;
     case 1:
         print "i equals 1";
         break;
     case 2:
         print "i equals 2";
         break;
 }
      

It is important to understand how the switch statement is executed in order to avoid messups. The switch statement executes line by line (actually, statement by statement). In the beginning, no code is executed. Only when a case statement is found with a value that matches the value of the switch expression, PHP begins to execute the statements. PHP continues to execute the statements until the end of the switch block, or the first time it sees a break statement. If you don't write a break statement at the end of a case's statement list, PHP will go on executing the statements of the following case. For example:

 /* example 3 */
 
 switch ($i) {
     case 0:
         print "i equals 0";
     case 1:
         print "i equals 1";
     case 2:
         print "i equals 2";
 }
      

Here, if $i equals to 0, PHP would execute all of the print statements! If $i equals to 1, PHP would execute the last two print statements, and only if $i equals to 2, you'd get the 'expected' behavior and only 'i equals 2' would be displayed. So, it's important not to forget break statements (even though you may want to avoid supplying them on purpose under certain circumstances).

A special case is the default case. This case matches anything that wasn't matched by the other cases. For example:

 /* example 4 */
 
 switch ($i) {
     case 0:
         print "i equals 0";
         break;
     case 1:
         print "i equals 1";
         break;
     case 2:
         print "i equals 2";
         break;
     default:
         print "i is not equal to 0, 1 or 2";
 }
      

Another fact worth mentioning is that the case expression may be any expression that evaluates to a scalar type, that is, integer or floating-point numbers and strings. Arrays or objects are meaningless in that context.

require

The require statement replaces itself with the specified file, much like the C preprocessor's #include works.

This means that you can't put a require statement inside of a loop structure and expect it to include the contents of a different file on each iteration. To do that, use an include statement.

 require 'header.inc';
      

include

The include statement includes and evaluates the specified file.

This happens each time the include statement is encountered, so you can use an include statement within a looping structure to include a number of different file.

 $files = array ('first.inc', 'second.inc', 'third.inc');
 for ($i = 0; $i < count($files); $i++) {
     include $files[$i];
 }
      

include differs from require in that the include statement is re-evaluated each time it is encountered (and only when it is being executed), whereas the require statement is replaced by the required file when it is first encountered, whether the contents of the file will be evaluated or not (for example, if it is inside an if statement whose condition evaluated to false).

Because include is a special language construct, you must enclose it within a statement block if it is inside a conditional block.

 /* This is WRONG and will not work as desired. */
 
 if ($condition)
     include($file);
 else
     include($other);
 
 /* This is CORRECT. */
 
 if ($condition) {
     include($file);
 } else {
     include($other);
 }
      

When the file is evaluated, the parser begins in "HTML-mode" which will output the contents of the file until the first PHP start tag (<?) is encountered.

See also readfile(), require(), virtual().

function

A function may be defined using syntax such as the following:

 function foo ($arg_1, $arg_2, ..., $arg_n) {
     echo "Example function.\n";
     return $retval;
 }
      

Any valid PHP code may appear inside a function, even other functions and class definitions.

Functions must be defined before they are referenced.

Returning values

Values are returned by using the optional return statement. Any type may be returned, including lists and objects.

 function my_sqrt ($num) {
     return $num * $num;
 }
 echo my_sqrt (4);   // outputs '16'.
       

Multiple values may not be returned, but the same effect can be achieved by returning a list:

 function foo() {
    return array (0, 1, 2);
 }
 list ($zero, $one, $two) = foo();
       

Arguments

Information may be passed to functions via the argument list, which is a comma-delimited list of variables and/or constants.

PHP supports passing arguments by value (the default), passing by reference, and default argument values. Variable-length argument lists are not supported, but a similar effect may be achieved by passing arrays.

 function takes_array($input) {
     echo "$input[0] + $input[1] = ", $input[0]+$input[1];
 }
       

Passing by reference

By default, function arguments are passed by value. If you wish to allow a function to modify its arguments, you may pass them by reference.

If you wish a function's argument to always be passed by reference, you can prepend an ampersand (&) to the argument name in the function definition:

 function foo( &$bar ) {
     $bar .= 'and something extra.';
 }
 $str = 'This is a string, ';
 foo ($str);
 echo $str;    // outputs 'This is a string, and something extra.'
        

If you wish to pass a variable by reference to a function which does not do this by default, you may prepend an ampersand to the argument name in the function call:

 function foo ($bar) {
     $bar .= ' and something extra.';
 }
 $str = 'This is a string, ';
 foo ($str);
 echo $str;    // outputs 'This is a string, '
 foo (&$str);
 echo $str;    // outputs 'This is a string, and something extra.'
        

Default values

A function may define C++-style default values for scalar arguments as follows:

 function makecoffee ($type = "cappucino") {
     echo "Making a cup of $type.\n";
 }
 echo makecoffee ();
 echo makecoffee ("espresso");
        

The output from the above snippet is:

 Making a cup of cappucino.
 Making a cup of espresso.
       

The default value must be a constant expression, not (for example) a variable or class member.

Note that when using default arguments, any defaults should be on the right side of any non-default arguments; otherwise, things will not work as expected. Consider the following code snippet:

 function makeyogurt ($type = "acidophilus", $flavour) {
     return "Making a bowl of $type $flavour.\n";
 }
 
 echo makeyogurt ("raspberry");   // won't work as expected
        

The output of the above example is:

 Warning: Missing argument 2 in call to makeyogurt() in 
 /usr/local/etc/httpd/htdocs/php3test/functest.html on line 41
 Making a bowl of raspberry .
       

Now, compare the above with this:

 function makeyogurt ($flavour, $type = "acidophilus") {
     return "Making a bowl of $type $flavour.\n";
 }
 
 echo makeyogurt ("raspberry");   // works as expected
        

The output of this example is:

 Making a bowl of acidophilus raspberry.
      

old_function

The old_function statement allows you to declare a function using a syntax identical to PHP/FI2 (except you must replace 'function' with 'old_function'.

This is a deprecated feature, and should only be used by the PHP/FI2->PHP3 convertor.

Functions declared as old_function cannot be called from PHP's internal code. Among other things, this means you can't use them in functions such as usort(), array_walk(), and register_shutdown_function(). You can get around this limitation by writing a wrapper function (in normal PHP3 form) to call the old_function.

class

A class is a collection of variables and functions working with these variables. A class is defined using the following syntax:

 <?php
 class Cart {
     var $items;  // Items in our shopping cart
   
     // Add $num articles of $artnr to the cart
 
     function add_item ($artnr, $num) {
         $this->items[$artnr] += $num;
     }
   
     // Take $num articles of $artnr out of the cart
 
     function remove_item ($artnr, $num) {
         if ($this->items[$artnr] > $num) {
             $this->items[$artnr] -= $num;
             return true;
         } else {
             return false;
         }   
     }
 }
 ?>
      

This defines a class named Cart that consists of an associative array of articles in the cart and two functions to add and remove items from this cart.

Classes are types, that is, they are blueprints for actual variables. You have to create a variables of the desired type with the new operator.

 $cart = new Cart;
 $cart->add_item("10", 1);
     

This creates an object $cart of the class Cart. The function add_item() of that object is being called to add 1 item of article number 10 to the cart.

Classes can be extensions of other classes. The extended or derived class has all variables and functions of the base class and what you add in the extended definition. This is done using the extends keyword.

 class Named_Cart extends Cart {
     var $owner;
  
     function set_owner ($name) {
         $this->owner = $name;
     }
 }
     

This defines a class Named_Cart that has all variables and functions of Cart plus an additional variable $owner and an additional function set_owner(). You create a named cart the usual way and can now set and get the carts owner. You can still use normal cart functions on named carts:

 $ncart = new Named_Cart;    // Create a named cart
 $ncart->set_owner ("kris"); // Name that cart
 print $ncart->owner;        // print the cart owners name
 $ncart->add_item ("10", 1); // (inherited functionality from cart)
     

Within functions of a class the variable $this means this object. You have to use $this->something to access any variable or function named something within your current object.

Constructors are functions in a class that are automatically called when you create a new instance of a class. A function becomes a constructor when it has the same name as the class.

 class Auto_Cart extends Cart {
     function Auto_Cart () {
         $this->add_item ("10", 1);
     }
 }
     

This defines a class Auto_Cart that is a Cart plus a constructor which initializes the cart with one item of article number "10" each time a new Auto_Cart is being made with "new". Constructors can also take arguments and these arguments can be optional, which makes them much more useful.

 class Constructor_Cart {
     function Constructor_Cart ($item = "10", $num = 1) {
         $this->add_item ($item, $num);
     }
 }
 
 // Shop the same old boring stuff.
 
 $default_cart   = new Constructor_Cart;
 
 // Shop for real...
 
 $different_cart = new Constructor_Cart ("20", 17);
     

Caution

For derived classes, the constructor of the parent class is not automatically called when the derived class's constructor is called.