5.7. Traversing ArraysThe most common task with arrays is to do something with every element—for instance, sending mail to each element of an array of addresses, updating each file in an array of filenames, or adding up each element of an array of prices. There are several ways to traverse arrays in PHP, and the one you choose will depend on your data and the task you're performing. 5.7.1. The foreach ConstructThe most common way to loop over elements of an array is to use the foreach construct: $addresses = array('spam@cyberpromo.net', 'abuse@example.com'); foreach ($addresses as $value) { echo "Processing $value\n"; } Processing spam@cyberpromo.net Processing abuse@example.com PHP executes the body of the loop (the echo statement) once for each element of $addresses in turn, with $value set to the current element. Elements are processed by their internal order. An alternative form of foreach gives you access to the current key: $person = array('name' => 'Fred', 'age' => 35, 'wife' => 'Wilma'); foreach ($person as $k => $v) { echo "Fred's $k is $v\n"; } Fred's name is Fred Fred's age is 35 Fred's wife is Wilma In this case, the key for each element is placed in $k and the corresponding value is placed in $v. The foreach construct does not operate on the array itself, but rather on a copy of it. You can insert or delete elements in the body of a foreach loop, safe in the knowledge that the loop won't attempt to process the deleted or inserted elements. 5.7.2. The Iterator FunctionsEvery PHP array keeps track of the current element you're working with; the pointer to the current element is known as the iterator. PHP has functions to set, move, and reset this iterator. The iterator functions are:
The each( ) function is used to loop over the elements of an array. It processes elements according to their internal order: reset($addresses); while (list($key, $value) = each($addresses)) { echo "$key is $value<BR>\n"; } 0 is spam@cyberpromo.net 1 is abuse@example.com This approach does not make a copy of the array, as foreach does. This is useful for very large arrays when you want to conserve memory. The iterator functions are useful when you need to consider some parts of the array separately from others. Example 5-1 shows code that builds a table, treating the first index and value in an associative array as table column headings. Example 5-1. Building a table with the iterator functions$ages = array('Person' => 'Age', 'Fred' => 35, 'Barney' => 30, 'Tigger' => 8, 'Pooh' => 40); // start table and print heading reset($ages); list($c1, $c2) = each($ages); echo("<table><tr><th>$c1</th><th>$c2</th></tr>\n"); // print the rest of the values while (list($c1,$c2) = each($ages)) { echo("<tr><td>$c1</td><td>$c2</td></tr>\n"); } // end the table echo("</table>"); <table><tr><th>Person</th><th>Age</th></tr> <tr><td>Fred</td><td>35</td></tr> <tr><td>Barney</td><td>30</td></tr> <tr><td>Tigger</td><td>8</td></tr> <tr><td>Pooh</td><td>40</td></tr> </table> 5.7.3. Using a for LoopIf you know that you are dealing with an indexed array, where the keys are consecutive integers beginning at 0, you can use a for loop to count through the indexes. The for loop operates on the array itself, not on a copy of the array, and processes elements in key order regardless of their internal order. Here's how to print an array using for: $addresses = array('spam@cyberpromo.net', 'abuse@example.com'); for($i = 0; $i < count($array); $i++) { $value = $addresses[$i]; echo "$value\n"; } spam@cyberpromo.net abuse@example.com 5.7.4. Calling a Function for Each Array ElementPHP provides a mechanism, array_walk( ), for calling a user-defined function once per element in an array: array_walk(array, function_name); The function you define takes in two or, optionally, three arguments: the first is the element's value, the second is the element's key, and the third is a value supplied to array_walk( ) when it is called. For instance, here's another way to print table columns made of the values from an array: function print_row($value, $key) { print("<tr><td>$value</td><td>$key</td></tr>\n"); } $person = array('name' => 'Fred', 'age' => 35, 'wife' => 'Wilma'); array_walk($person, 'print_row'); A variation of this example specifies a background color using the optional third argument to array_walk( ). This parameter gives us the flexibility we need to print many tables, with many background colors: function print_row($value, $key, $color) { print("<tr><td bgcolor=$color>$value</td><td bgcolor=$color>$key</td></tr>\n"); } $person = array('name' => 'Fred', 'age' => 35, 'wife' => 'Wilma'); array_walk($person, 'print_row', 'blue'); The array_walk( ) function processes elements in their internal order. 5.7.5. Reducing an ArrayA cousin of array_walk( ), array_reduce( ) , applies a function to each element of the array in turn, to build a single value: $result = array_reduce(array, function_name [, default ]); The function takes two arguments: the running total, and the current value being processed. It should return the new running total. For instance, to add up the squares of the values of an array, use: function add_up ($running_total, $current_value) { $running_total += $current_value * $current_value; return $running_total; } $numbers = array(2, 3, 5, 7); $total = array_reduce($numbers, 'add_up'); // $total is now 87 The array_reduce( ) line makes these function calls: add_up(2,3) add_up(13,5) add_up(38,7) The default argument, if provided, is a seed value. For instance, if we change the call to array_reduce( ) in the previous example to: $total = array_reduce($numbers, 'add_up', 11); The resulting function calls are: add_up(11,2) add_up(13,3) add_up(16,5) add_up(21,7) If the array is empty, array_reduce( ) returns the default value. If no default value is given and the array is empty, array_reduce( ) returns NULL. 5.7.6. Searching for ValuesThe in_array( ) function returns true or false, depending on whether the first argument is an element in the array given as the second argument: if (in_array(to_find, array [, strict])) { ... } If the optional third argument is true, the types of to_find and the value in the array must match. The default is to not check the types. Here's a simple example: $addresses = array('spam@cyberpromo.net', 'abuse@example.com', 'root@example.com'); $got_spam = in_array('spam@cyberpromo.net', $addresses); // $got_spam is true $got_milk = in_array('milk@tucows.com', $addresses); // $got_milk is false PHP automatically indexes the values in arrays, so in_array( ) is much faster than a loop that checks every value to find the one you want. Example 5-2 checks whether the user has entered information in all the required fields in a form. Example 5-2. Searching an array<?php function have_required($array , $required_fields) { foreach($required_fields as $field) { if(empty($array[$field])) return false; } return true; } if($submitted) { echo '<p>You '; echo have_required($_POST, array('name', 'email_address')) ? 'did' : 'did not'; echo ' have all the required fields.</p>'; } ?> <form action="<?= $PHP_SELF; ?>" method="POST"> <p> Name: <input type="text" name="name" /><br /> Email address: <input type="text" name="email_address" /><br /> Age (optional): <input type="text" name="age" /> </p> <p align="center"> <input type="submit" value="submit" name="submitted" /> </p> </form> A variation on in_array( ) is the array_search( ) function. While in_array( ) returns true if the value is found, array_search( ) returns the key of the found element: $person = array('name' => 'Fred', 'age' => 35, 'wife' => 'Wilma'); $k = array_search($person, 'Wilma'); echo("Fred's $k is Wilma\n"); Fred's wife is Wilma The array_search( ) function also takes the optional third strict argument, which requires the types of the value being searched for and the value in the array to match. Copyright © 2003 O'Reilly & Associates. All rights reserved. |
|