CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in
Add ListingModify ListingTell A FriendLink to TPASubscribeNew ListingsCool ListingsTop RatedRandom Link
Newest Reviews
  • review
  • hagen software
  • NOT GPL!
  • Hagan Software
  • Wasted Time with ...
  • poor pre-sale sup...
  • no response
  • rating the offer
  • Good Stuff
  • Good idea but use...


  • Brochure Templates  
     
    Perl Archive : TLC : Programming : PHP : Book Chapter : PHP and MySQL Web Development (Chapter 3: Using Arrays)
    Guide Search entire directory 
     

    Date Published: 2002-08-26

    This chapter shows you how to use an important programming construct—arrays. The variables that we looked at in the previous chapters are scalar variables, which store a single value. An array is a variable that stores a set or sequence of values. One array can have many elements. Each element can hold a single value, such as text or numbers, or another array. An array containing other arrays is known as a multidimensional array.

    PHP and MySQL Web Development (Chapter 3: Using Arrays)

    Authors: Luke Welling and Laura Thomson
    Publisher: Sams
    ISBN: 0672317842
    Purchase Online: Amazon.com $34.99
      Barnes & Noble $39.99

    Chapter 3: Using Arrays

    This chapter shows you how to use an important programming construct—arrays. The variables that we looked at in the previous chapters are scalar variables, which store a single value. An array is a variable that stores a set or sequence of values. One array can have many elements. Each element can hold a single value, such as text or numbers, or another array. An array containing other arrays is known as a multidimensional array.

    PHP supports both numerically indexed and associative arrays. You will probably be familiar with numerically indexed arrays if you've used a programming language, but unless you use PHP or Perl, you might not have seen associative arrays before. Associative arrays let you use more useful values as the index. Rather than each element having a numeric index, they can have words or other meaningful information.

    We will continue developing the Bob's Auto parts example using arrays to work more easily with repetitive information such as customer orders. Likewise, we will write shorter, tidier code to do some of the things we did with files in the previous chapter.

    Key topics covered in this chapter include

    • What is an array?

    • Numerically indexed arrays

    • Associative arrays

    • Multidimensional arrays

    • Sorting arrays

    • Further reading

    What Is an Array?

    We looked at scalar variables in Chapter 1, "PHP Crash Course." A scalar variable is a named location in which to store a value; similarly, an array is a named place to store a set of values, thereby allowing you to group common scalars.

    Bob's product list will be the array for our example. In Figure 3.1, you can see a list of three products stored in an array format and one variable, called $products, which stores the three values. (We'll look at how to create a variable like this in a minute.)


    Figure 3.1

    Bob's products can be stored in an array.

    After we have the information as an array, we can do a number of useful things with it. Using the looping constructs from Chapter 1, we can save work by performing the same actions on each value in the array. The whole set of information can be moved around as a single unit. This way, with a single line of code, all the values can be passed to a function. For example, we might want to sort the products alphabetically. To achieve this, we could pass the entire array to PHP's sort() function.

    The values stored in an array are called the array elements. Each array element has an associated index (also called a key) that is used to access the element.

    Arrays in most programming languages have numerical indexes that typically start from zero or one. PHP supports this type of array.

    PHP also supports associative arrays, which will be familiar to Perl programmers. Associative arrays can have almost anything as the array indices, but typically use strings.

    We will begin by looking at numerically indexed arrays.

    Numerically Indexed Arrays

    These arrays are supported in most programming languages. In PHP, the indices start at zero by default, although you can alter this.

    Initializing Numerically Indexed Arrays

    To create the array shown in Figure 3.1, use the following line of PHP code:

    $products = array( "Tires", "Oil", "Spark Plugs" );

    This will create an array called products containing the three values given—"Tires", "Oil", and "Spark Plugs". Note that, like echo, array() is actually a language construct rather than a function.

    Depending on the contents you need in your array, you might not need to manually initialize them as in the preceding example.

    If you have the data you need in another array, you can simply copy one array to another using the = operator.

    If you want an ascending sequence of numbers stored in an array, you can use the range() function to automatically create the array for you. The following line of code will create an array called numbers with elements ranging from 1 to 10:

    $numbers = range(1,10);

    If you have the information stored in file on disk, you can load the array contents directly from the file. We'll look at this later in this chapter under the heading "Loading Arrays from Files."

    If you have the data for your array stored in a database, you can load the array contents directly from the database. This is covered in Chapter 10, "Accessing Your MySQL Database from the Web with PHP."

    You can also use various functions to extract part of an array or to reorder an array. We'll look at some of these functions later in this chapter, under the heading "Other Array Manipulations."

    Accessing Array Contents

    To access the contents of a variable, use its name. If the variable is an array, access the contents using the variable name and a key or index. The key or index indicates which stored values we access. The index is placed in square brackets after the name.

    Type $products[0], $products[1], and $products[2] to use the contents of the products array.

    Element zero is the first element in the array. This is the same numbering scheme as used in C, C++, Java, and a number of other languages, but it might take some getting used to if you are not familiar with it.

    As with other variables, array elements contents are changed by using the = operator. The following line will replace the first element in the array "Tires" with "Fuses".

    $products[0] = "Fuses";

    The following line could be used to add a new element—"Fuse"—to the end of the array, giving us a total of four elements:

    $products[3] = "Fuses";

    To display the contents, we could type

    echo "$products[0] $products[1] $products[2] $products[3]";

    Like other PHP variables, arrays do not need to be initialized or created in advance. They are automatically created the first time you use them.

    The following code will create the same $products array:

    $products[0] = "Tires";
    $products[1] = "Oil";
    $products[2] = "Spark Plugs";

    If $products does not already exist, the first line will create a new array with just one element. The subsequent lines add values to the array.

    Using Loops to Access the Array

    Because the array is indexed by a sequence of numbers, we can use a for loop to more easily display the contents:

    for ( $i = 0; $i<3; $i++ )
     echo "$products[$i] ";

    This loop will give similar output to the preceding code, but will require less typing than manually writing code to work with each element in a large array. The ability to use a simple loop to access each element is a nice feature of numerically indexed arrays. Associative arrays are not quite so easy to loop through, but do allow indexes to be meaningful.

    Associative Arrays

    In the products array, we allowed PHP to give each item the default index. This meant that the first item we added became item 0, the second item 1, and so on. PHP also supports associative arrays. In an associative array, we can associate any key or index we want with each value.

    Initializing an Associative Array

    The following code creates an associative array with product names as keys and prices as values.

    $prices = array( "Tires"=>100, "Oil"=>10, "Spark Plugs"=>4 );

    Accessing the Array Elements

    Again, we access the contents using the variable name and a key, so we can access the information we have stored in the prices array as $prices[ "Tires" ], $prices[ "Oil" ], and $prices[ "Spark Plugs" ].

    Like numerically indexed arrays, associative arrays can be created and initialized one element at a time.

    The following code will create the same $prices array. Rather than creating an array with three elements, this version creates an array with only one element, and then adds two more.

    $prices = array( "Tires"=>100 );
    $prices["Oil"] = 10;
    $prices["Spark Plugs"] = 4;

    Here is another slightly different, but equivalent piece of code. In this version, we do not explicitly create an array at all. The array is created for us when we add the first element to it.

    $prices["Tires"] = 100;
    $prices["Oil"] = 10;
    $prices["Spark Plugs"] = 4;

    Using Loops with each() and list()

    Because the indices in this associative array are not numbers, we cannot use a simple counter in a for loop to work with the array. The following code lists the contents of our $prices array:

    while( $element = each( $prices ) )
    {
     echo $element[ "key" ];
     echo " - ";
     echo $element[ "value" ];
     echo "<br>";
    }

    The output of this script fragment is shown in Figure 3.2.


    Figure 3.2

    An each statement can be used to loop through arrays.

    In Chapter 1, we looked at while loops and the echo statement. The preceding code uses the each() function, which we have not used before. This function returns the current element in an array and makes the next element the current one. Because we are calling each() within a while loop, it returns every element in the array in turn and stops when the end of the array is reached.

    In this code, the variable $element is an array. When we call each(), it gives us an array with four values and the four indexes to the array locations. The locations key and 0 contain the key of the current element, and the locations value and 1 contain the value of the current element. Although it makes no difference which you choose, we have chosen to use the named locations, rather than the numbered ones.

    There is a more elegant and more common way of doing the same thing. The function list() can be used to split an array into a number of values. We can separate two of the values that the each() function gives us like this:

    $list( $product, $price ) = each( $prices );

    This line uses each() to take the current element from $prices, return it as an array, and make the next element current. It also uses list() to turn the 0 and 1 elements from the array returned by each() into two new variables called $product and $price.

    We can loop through the entire $prices array, echoing the contents using this short script.

    while ( list( $product, $price ) = each( $prices ) )
     echo "$product - $price<br>";

    This has the same output as the previous script, but is easier to read because list() allows us to assign names to the variables.

    One thing to note when using each() is that the array keeps track of the current element. If we want to use the array twice in the same script, we need to set the current element back to the start of the array using the function reset(). To loop through the prices array again, we type the following:

    reset($prices);
    while ( list( $product, $price ) = each( $prices ) )
     echo "$product - $price<br>";

    This sets the current element back to the start of the array, and allows us to go through again.

    Multidimensional Arrays

    Arrays do not have to be a simple list of keys and values—each location in the array can hold another array. This way, we can create a two-dimensional array. You can think of a two dimensional array as a matrix, or grid, with width and height or rows and columns.

    If we want to store more than one piece of data about each of Bob's products, we could use a two-dimensional array.

    Figure 3.3 shows Bob's products represented as a two-dimensional array with each row representing an individual product and each column representing a stored product attribute.


    Figure 3.3

    We can store more information about Bob's products in a two-dimensional array.

    Using PHP, we would write the following code to set up the data in the array shown in Figure 3.3.

    $products = array( array( "TIR", "Tires", 100 ),
              array( "OIL", "Oil", 10 ),
              array( "SPK", "Spark Plugs", 4 ) );

    You can see from this definition that our products array now contains three arrays.

    To access the data in a one-dimensional array, recall that we need the name of the array and the index of the element. A two-dimensional array is similar, except that each element has two indices—a row and a column. (The top row is row 0 and the far left column is column 0.)

    To display the contents of this array, we could manually access each element in order like this:

    echo "|".$products[0][0]."|".$products[0][1]."|".$products[0][2]."|<BR>";
    echo "|".$products[1][0]."|".$products[1][1]."|".$products[1][2]."|<BR>";
    echo "|".$products[2][0]."|".$products[2][1]."|".$products[2][2]."|<BR>";

    Alternatively, we could place a for loop inside another for loop to achieve the same result.

    for ( $row = 0; $row < 3; $row++ )
    {
     for ( $column = 0; $column < 3; $column++ )
     {
      echo "|".$products[$row][$column];
     }
     echo "|<BR>";
    }

    Both versions of this code produce the same output in the browser:

    |TIR|Tires|100|
    |OIL|Oil|10|
    |SPK|Spark Plugs|4|

    The only difference between the two examples is that your code will be shorter if you use the second version with a large array.

    You might prefer to create column names instead of numbers as shown in Figure 3.3. To do this, you can use associative arrays. To store the same set of products, with the columns named as they are in Figure 3.3, you would use the following code:

    $products = array( array( Code => "TIR", 
                 Description => "Tires", 
                 price => 100 
                ),
              array( Code => "OIL", 
                 Description => "Oil", 
                 price => 10 
                ),
              array( Code => "SPK", 
                 Description => "Spark Plugs", 
                 price =>4 
                ) 
             );

    This array is easier to work with if you want to retrieve a single value. It is easier to remember that the description is stored in the Description column than to remember that it is stored in column 1. Using associative arrays, you do not need to remember that an item is stored at [x][y]. You can easily find your data by referring to a location with meaningful row and column names.

    We do however lose the ability to use a simple for loop to step through each column in turn. Here is one way to write code to display this array:

    for ( $row = 0; $row < 3; $row++ )
    {
     echo "|".$products[$row]["Code"]."|".$products[$row]["Description"].
        "|".$products[$row]["Price"]."|<BR>";
    }

    Using a for loop, we can step through the outer, numerically indexed $products array. Each row in our $products array is an associative array. Using the each() and list() functions in a while loop, we can step through the associative arrays. Therefore, we need a while loop inside a for loop.

    for ( $row = 0; $row < 3; $row++ )
    {
     while ( list( $key, $value ) = each( $products[ $row ] ) )
     {
      echo "|$value";
     }
     echo "|<BR>";
    }

    We do not need to stop at two dimensions—in the same way that array elements can hold new arrays, those new arrays in turn can hold more arrays.

    A three-dimensional array has height, width, and depth. If you are comfortable thinking of a two-dimensional array as a table with rows and columns, imagine a pile or deck of those tables. Each element will be referenced by its layer, row, and column.

    If Bob divided his products into categories, we could use a three-dimensional array to store them. Figure 3.4 shows Bob's products in a three-dimensional array.


    Figure 3.4

    This three-dimensional array allows us to divide products into categories.

    From the code that defines this array, you can see that a three-dimensional array is an array containing arrays of arrays.

    $categories = array( array ( array( "TIR", "Tires", 100 ),
                   array( "OIL", "Oil", 10 ),
                   array( "SPK", "Spark Plugs", 4 )
                  ),
               array ( array( "TIR", "Tires", 100 ),
                   array( "OIL", "Oil", 10 ),
                   array( "SPK", "Spark Plugs", 4 )
                  ),
               array ( array( "TIR", "Tires", 100 ),
                   array( "OIL", "Oil", 10 ),
                   array( "SPK", "Spark Plugs", 4 )
                  )
              );

    Because this array has only numeric indices, we can use nested for loops to display its contents.

    for ( $layer = 0; $layer < 3; $layer++ )
    {
     echo "Layer $layer<BR>";
     for ( $row = 0; $row < 3; $row++ )
     {
      for ( $column = 0; $column < 3; $column++ )
      {
       echo "|".$categories[$layer][$row][$column];
      }
      echo "|<BR>";
     }
    }

    Because of the way multidimensional arrays are created, we could create four-, five-, or six-dimensional arrays. There is no language limit to the number of dimensions, but it is difficult for people to visualize constructs with more than three dimensions. Most real-world problems match logically with constructs of three or fewer dimensions.

    Sorting Arrays

    It is often useful to sort related data stored in an array. Taking a one-dimensional array and sorting it into order is quite easy.

    Using sort()

    The following code results in the array being sorted into ascending alphabetical order:

    $products = array( "Tires", "Oil", "Spark Plugs" );
    sort($products);

    Our array elements will now be in the order Oil, Spark Plugs, Tires.

    We can sort values by numerical order too. If we have an array containing the prices of Bob's products, we can sort it into ascending numeric order as shown:

    $prices = array( 100, 10, 4 );
    sort($prices);

    The prices will now be in the order 4, 10, 100.

    Note that the sort function is case sensitive. All capital letters come before all lowercase letters. So 'A' is less than 'Z', but 'Z' is less than 'a'.

    Using asort() and ksort() to Sort Associative Arrays

    If we are using an associative array to store items and their prices, we need to use different kinds of sort functions to keep keys and values together as they are sorted.

    The following code creates an associative array containing the three products and their associated prices, and then sorts the array into ascending price order.

    $prices = array( "Tires"=>100, "Oil"=>10, "Spark Plugs"=>4 );
    asort($prices);

    The function asort() orders the array according to the value of each element. In the array, the values are the prices and the keys are the textual descriptions. If instead of sorting by price we want to sort by description, we use ksort(), which sorts by key rather than value. This code will result in the keys of the array being ordered alphabetically—Oil, Spark Plugs, Tires.

    $prices = array( "Tires"=>100, "Oil"=>10, "Spark Plugs"=>4 );
    ksort($prices);

    Sorting in Reverse

    You have seen sort(), asort(), and ksort(). These three different sorting functions all sort an array into ascending order. Each of these functions has a matching reverse sort function to sort an array into descending order. The reverse versions are called rsort(), arsort(), and krsort().

    The reverse sort functions are used in the same way as the sorting functions. The rsort() function sorts a single dimensional numerically indexed array into descending order. The arsort() function sorts a one-dimensional associative array into descending order using the value of each element. The krsort() function sorts a one-dimensional associative array into descending order using the key of each element.

    Sorting Multidimensional Arrays

    Sorting arrays with more than one dimension, or by something other than alphabetical or numerical order, is more complicated. PHP knows how to compare two numbers or two text strings, but in a multidimensional array, each element is an array. PHP does not know how to compare two arrays, so you need to create a method to compare them. Most of the time, the order of the words or numbers is fairly obvious—but for complicated objects, it becomes more problematic.

    User Defined Sorts

    Here is the definition of a two-dimensional array we used earlier. This array stores Bob's three products with a code, a description, and a price for each.

    $products = array( array( "TIR", "Tires", 100 ),
              array( "OIL", "Oil", 10 ),
              array( "SPK", "Spark Plugs", 4 ) );

    If we sort this array, what order will the values end up in? Because we know what the contents represent, there are at least two useful orders. We might want the products sorted into alphabetical order using the description or by numeric order by the price. Either result is possible, but we need to use the function usort() and tell PHP how to compare the items. To do this, we need to write our own comparison function.

    The following code sorts this array into alphabetical order using the second column in the array—the description.

    function compare($x, $y)
    {
     if ( $x[1] == $y[1] )
      return 0;
     else if ( $x[1] < $y[1] )
      return -1;
     else
      return 1;
    }
    
    usort($products, compare);

    So far in this book, we have called a number of the built-in PHP functions. To sort this array, we have defined a function of our own. We will examine writing functions in detail in Chapter 5, "Reusing Code and Writing Functions," but here is a brief introduction.

    We define a function using the keyword function. We need to give the function a name. Names should be meaningful, so we'll call it compare(). Many functions take parameters or arguments. Our compare() function takes two, one called x and one called y. The purpose of this function is to take two values and determine their order.

    For this example, the x and y parameters will be two of the arrays within the main array, each representing one product. To access the Description of the array x, we type $x[1] because the Description is the second element in these arrays, and numbering starts at zero. We use $x[1] and $y[1] to compare the Descriptions from the arrays passed into the function.

    When a function ends, it can give a reply to the code that called it. This is called returning a value. To return a value, we use the keyword return in our function. For example, the line return 1; sends the value 1 back to the code that called the function.

    To be used by usort(), the compare() function must compare x and y. The function must return 0 if x equals y, a negative number if it is less, and a positive number if it is greater. Our function will return 0, 1, or –1, depending on the values of x and y.

    The final line of code calls the built-in function usort() with the array we want sorted ($products) and the name of our comparison function (compare()).

    If we want the array sorted into another order, we can simply write a different comparison function. To sort by price, we need to look at the third column in the array, and create this comparison function:

    function compare($x, $y)
    {
     if ( $x[2] == $y[2] )
      return 0;
     else if ( $x[2] < $y[2] )
      return -1;
     else
      return 1;
    }

    When usort($products, compare) is called, the array will be placed in ascending order by price.

    The "u" in usort() stands for "user" because this function requires a user-defined comparison function. The uasort() and uksort() versions of asort and ksort also require a user-defined comparison function.

    Similar to asort(), uasort() should be used when sorting an associative array by value. Use asort if your values are simple numbers or text. Define a comparison function and use uasort() if your values are more complicated objects such as arrays.

    Similar to ksort(), uksort() should be used when sorting an associative array by key. Use ksort if your keys are simple numbers or text. Define a comparison function and use uksort() if your keys are more complicated objects such as arrays.

    Reverse User Sorts

    The functions sort(), asort(), and ksort() all have a matching reverse sort with an "r" in the function name. The user-defined sorts do not have reverse variants, but you can sort a multidimensional array into reverse order. You provide the comparison function, so write a comparison function that returns the opposite values. To sort into reverse order, the function will need to return 1 if x is less than y and –1 if x is greater than y. For example

    function reverseCompare($x, $y)
    {
     if ( $x[2] == $y[2] )
      return 0;
     else if ( $x[2] < $y[2] )
      return 1;
     else
      return -1;
    }

    Calling usort($products, reverseCompare) would now result in the array being placed in descending order by price.

    Reordering Arrays

    For some applications, you might want to manipulate the order of the array in other ways. The function shuffle() randomly reorders the elements of your array. The function array_reverse() gives you a copy of your array with all the elements in reverse order.

    Using shuffle()

    Bob wants to feature a small number of his products on the front page of his site. He has a large number of products, but would like three randomly selected items shown on the front page. So that repeat visitors do not get bored, he would like the three chosen products to be different for each visit. He can easily accomplish his goal if all his products are in an array. Listing 3.1 displays three randomly chosen pictures by shuffling the array into a random order and then displaying the first three.

    Listing 3.1  bobs_front_page.php—Using PHP to Produce a Dynamic Front Page for Bob's Auto Parts

    <?
     $pictures = array("tire.jpg", "oil.jpg", "spark_plug.jpg",
              "door.jpg", "steering_wheel.jpg",
              "thermostat.jpg", "wiper_blade.jpg",
              "gasket.jpg", "brake_pad.jpg");
     shuffle($pictures);
    ?>
    <html>
    <head>
     <title>Bob's Auto Parts</title>
    </head>
    <body>
     <center>
      <h1>Bob's Auto Parts</H1>
      <table width = 100%>
       <tr>
    <?
     for ( $i = 0; $i < 3; $i++ )
     {
      echo "<td align = center><img src=\"";
      echo $pictures[$i];
      echo "\" width = 100 height = 100></td>";
     }
    ?>
       </tr>
      </table>
     </center>
    </body>
    </html>

    Because the code selects random pictures, it produces a different page nearly every time you load it, as shown in Figure 3.5.


    Figure 3.5

    The shuffle() function enables us to feature three randomly chosen products.

    Using array_reverse()

    The function array_reverse() takes an array and creates a new one with the same contents in reverse order. For example, there are a number of ways to create an array containing a countdown from ten to one.

    Because using range() alone creates an ascending sequence, we must then use rsort() to sort the numbers into descending order. Alternatively, we could create the array one element at a time by writing a for loop:

    $numbers = array();
    for($i=10; $i>0; $i--)
     array_push( $numbers, $i );

    A for() loop can go in descending order like this. We set the starting value high, and at the end of each loop use the -- operator to decrease the counter by one.

    We created an empty array, and then used array_push() for each element to add one new element to the end of an array. As a side note, the opposite of array_push() is array_pop(). This function removes and returns one element from the end of an array.

    Alternatively, we can use the array_reverse() function to reverse the array created by range().

    $numbers = range(1,10);
    $numbers = array_reverse($numbers);

    Note that array_reverse() returns a modified copy of the array. Because we did not want the original array, we simply stored the new copy over the original.

    Loading Arrays from Files

    In Chapter 2, "Storing and Retrieving Data," we stored customer orders in a file. Each line in the file looks something like

    15:42, 20th April 4 tires 1 oil 6 spark plugs $434.00 22 Short St, Smalltown

    To process or fulfill this order, we could load it back into an array. Listing 3.2 displays the current order file.

    Listing 3.2  vieworders.php—Using PHP to Display Orders for Bob

    $orders= file("../../orders/orders.txt");
    $number_of_orders = count($orders);
    if ($number_of_orders == 0)
    {
     echo "<p><strong>No orders pending. 
        Please try again later.</strong></p>";
    }
    for ($i=0; $i<$number_of_orders; $i++)
    {
     echo $orders[$i]."<br>";
    
    }

    This script produces almost exactly the same output as Listing 2.2 in the previous chapter, which is shown in Figure 2.4. This time, we are using the function file(), which loads the entire file into an array. Each line in the file becomes one element of an array.

    This code also uses the count() function to see how many elements are in an array.

    Furthermore, we could load each section of the order lines into separate array elements to process the sections separately or to format them more attractively. Listing 3.3 does exactly that.

    Listing 3.3  vieworders2.php—Using PHP to Separate, Format, and Display Orders for Bob

    <html>
    <head>
     <title>Bob's Auto Parts – Customer Orders</title>
    </head>
    <body>
    <h1>Bob's Auto Parts</h1>
    <h2>Customer Orders</h2>
    <?
      //Read in the entire file.
      //Each order becomes an element in the array
      $orders= file("../../orders/orders.txt");
      // count the number of orders in the array
      $number_of_orders = count($orders);
      if ($number_of_orders == 0)
      {
       echo "<p><strong>No orders pending.
         Please try again later.</strong></p>";
      }
      echo "<table border=1>\n";
      echo "<tr><th bgcolor = \"#CCCCFF\">Order Date</td>
           <th bgcolor = \"#CCCCFF\">Tires</td>
           <th bgcolor = \"#CCCCFF\">Oil</td>
           <th bgcolor = \"#CCCCFF\">Spark Plugs</td>
           <th bgcolor = \"#CCCCFF\">Total</td>
           <th bgcolor = \"#CCCCFF\">Address</td>
         <tr>";
      for ($i=0; $i<$number_of_orders; $i++)
      {
       //split up each line
       $line = explode( "\t", $orders[$i] );
       // keep only the number of items ordered
       $line[1] = intval( $line[1] );
       $line[2] = intval( $line[2] );
       $line[3] = intval( $line[3] );
       // output each order
       echo "<tr><td>$line[0]</td>
            <td align = right>$line[1]</td>
            <td align = right>$line[2]</td>
            <td align = right>$line[3]</td>
            <td align = right>$line[4]</td>
            <td>$line[5]</td>
          </tr>";
      }
      echo "</table>";
    ?>
    </body>
    
    </html>

    The code in Listing 3.3 loads the entire file into an array but unlike the example in Listing 3.2, here we are using the function explode() to split up each line, so that we can apply some processing and formatting before printing.

    The output from this script is shown in Figure 3.6.


    Figure 3.6

    After splitting order records with explode, we can put each part of an order in a different table cell for better looking output.

    The explode function has the following prototype:

    array explode(string separator, string string)

    In the previous chapter, we used the tab character as a delimiter when storing this data, so here we called

    explode( "\t", $orders[$i] )

    This "explodes" the passed-in string into parts. Each tab character becomes a break between two elements. For example, the string

    "15:42, 20th April\t4 tires\t1 oil\t 
    6 spark plugs\t$434.00\t22 Short St, Smalltown"

    is exploded into the parts "15:42, 20th April", "4 tires", "1 oil", "6 spark plugs", "$434.00", and "22 Short St, Smalltown".

    We have not done very much processing here. Rather than output tires, oil, and spark plugs on every line, we are only displaying the number of each and giving the table a heading row to show what the numbers represent.

    There are a number of ways that we could have extracted numbers from these strings. Here we used the function, intval(). As mentioned in Chapter 1, intval() converts a string to an integer. The conversion is reasonably clever and will ignore parts, such as the label in this example, that cannot be converted to an integer. We will cover various ways of processing strings in the next chapter.

    Other Array Manipulations

    So far, we have only covered about half the array processing functions. Many others will be useful from time to time.

    Navigating Within an Array: each, current(), reset(), end(), next(), pos(), and prev()

    We mentioned previously that every array has an internal pointer that points to the current element in the array. We indirectly used this pointer earlier when using the each() function, but we can directly use and manipulate this pointer.

    If we create a new array, the current pointer is initialized to point to the first element in the array. Calling current( $array_name ) returns the first element.

    Calling either next() or each() advances the pointer forward one element. Calling each( $array_name ) returns the current element before advancing the pointer. The function next() behaves slightly differently—calling next( $array_name ) advances the pointer and then returns the new current element.

    We have already seen that reset() returns the pointer to the first element in the array. Similarly, calling end( $array_name ) sends the pointer to the end of the array. The first and last element in the array are returned by reset() and end(), respectively.

    To move through an array in reverse order, we could use end() and prev(). The prev() function is the opposite of next(). It moves the current pointer back one and then returns the new current element.

    For example, the following code displays an array in reverse order:

    $value = end ($array);
    while ($value)
    {
     echo "$value<br>";
     $value = prev($array);
    }

    If $array was declared like this:

    $array = array(1, 2, 3);

    the output would appear in a browser as

    3
    2
    1

    Using each(), current(), reset(), end(), next(), pos(), and prev(), you can write your own code to navigate through an array in any order.

    Applying Any Function to Each Element in an Array: array_walk()

    Sometimes you might want to work with or modify every element in an array in the same way. The function array_walk() allows you to do this.

    The prototype of array_walk() is as follows:

    int array_walk(array arr, string func, [mixed userdata])

    Similar to the way we called usort() earlier, array_walk() expects you to declare a function of your own.

    As you can see, array_walk() takes three parameters. The first, arr, is the array to be processed. The second, func, is the name of a user-defined function that will be applied to each element in the array. The third parameter, userdata, is optional. If you use it, it will be passed through to your function as a parameter. You'll see how this works in a minute.

    A handy user-defined function might be one that displays each element with some specified formatting.

    The following code displays each element on a new line by calling the user-defined function myPrint() with each element of $array:

    function myPrint($value)
    {
     echo "$value<BR>";
    }
    array_walk($array, myPrint);

    The function you write needs to have a particular signature. For each element in the array, array_walk takes the key and value stored in the array, and anything you passed as userdata, and calls your function like this:

    Yourfunction(value, key, userdata)

    For most uses, your function will only be using the values in the array. For some, you might also need to pass a parameter to your function using the parameter userdata. Occasionally, you might be interested in the key of each element as well as the value. Your function can, as with MyPrint(), choose to ignore the key and userdata parameter.

    For a slightly more complicated example, we will write a function that modifies the values in the array and requires a parameter. Note that although we are not interested in the key, we need to accept it in order to accept the third parameter.

    function myMultiply(&$value, $key, $factor)
    {
     $value *= $factor;
    }
    array_walk(&$array, "myMultiply", 3);

    Here we are defining a function, myMultiply(), that will multiply each element in the array by a supplied factor. We need to use the optional third parameter to array_walk() to take a parameter to pass to our function and use it as the factor to multiply by. Because we need this parameter, we must define our function, myMultiply(), to take three parameters—an array element's value ($value), an array element's key ($key), and our parameter ($factor). We are choosing to ignore the key.

    A subtle point to note is the way we pass $value. The ampersand (&) before the variable name in the definition of myMultiply() means that $value will be passed by reference. Passing by reference allows the function to alter the contents of the array.

    We will address passing by reference in more detail in Chapter 5. If you are not familiar with the term, for now just note that to pass by reference, we place an ampersand before the variable name.

    Counting Elements in an Array: count(), sizeof(), and array_count_values()

    We used the function count() in an earlier example to count the number of elements in an array of orders. The function sizeof() has exactly the same purpose. Both these functions return the number of elements in an array passed to them. You will get a count of one for the number of elements in a normal scalar variable and 0 if you pass either an empty array or a variable that has not been set.

    The array_count_values() function is more complex. If you call array_count_values($array), this function counts how many times each unique value occurs in the array $array. (This is the set cardinality of the array.) The function returns an associative array containing a frequency table. This array contains all the unique values from $array as keys. Each key has a numeric value that tells you how many times the corresponding key occurs in $array.

    For example, the following code

    $array = array(4, 5, 1, 2, 3, 1, 2, 1);
    $ac = array_count_values($array);

    creates an array called $ac that contains

    Key Value
    4 1
    5 1
    1 3
    2 2
    3 1

    This indicates that 4, 5, and 3 occurred once in $array, 1 occurred three times, and 2 occurred twice.

    Converting Arrays to Scalar Variables: extract()

    If we have an associative array with a number of key value pairs, we can turn them into a set of scalar variables using the function extract(). The prototype for extract() is as follows:

    extract(array var_array [, int extract_type] [, string prefix] );

    The purpose of extract() is to take an array and create scalar variables with the names of the keys in the array. The values of these variables are set to the values in the array.

    Here is a simple example.

    $array = array( "key1" => "value1", "key2" => "value2", "key3" => "value3");
    extract($array);
    echo "$key1 $key2 $key3";

    This code produces the following output:

    value1 value2 value3

    The array had three elements with keys: key1, key2, and key3. Using extract(), we created three scalar variables, $key1, $key2, and $key3. You can see from the output that the values of $key1, $key2, and $key3 are "value1", "value2", and "value3", respectively. These values came from the original array.

    There are two optional parameters to extract(): extract_type and prefix. The variable extract_type tells extract() how to handle collisions. These are cases in which a variable already exists with the same name as a key. The default response is to overwrite the existing variable. Four allowable values for extract_type are shown in Table 3.1.

    Table 3.1  Allowed extract_types for extract()

    Type

    Meaning

    EXTR_OVERWRITE

    Overwrites the existing variable when a collision occurs.

    EXTR_SKIP

    Skips an element when a collision occurs.

    EXTR_PREFIX_SAME

    Creates a variable named $prefix_key when a collision occurs. You must supply prefix.

    EXTR_PREFIX_ALL

    Prefixes all variable names with prefix. You must supply prefix.


    The two most useful options are the default (EXTR_OVERWRITE) and EXTR_PREFIX_ALL. The other two options might be useful occasionally when you know that a particular collision will occur and want that key skipped or prefixed. A simple example using EXTR_PREFIX_ALL follows. You can see that the variables created are called prefix-underscore-keyname.

    $array = array( "key1" => "value1", "key2" => "value2", "key3" => "value3");
    extract($array, EXTR_PREFIX_ALL, "myPrefix");
    echo "$myPrefix_key1 $myPrefix_key2 $myPrefix_key3";

    This code will again produce the output: value1 value2 value3.

    Note that for extract() to extract an element, that element's key must be a valid variable name, which means that keys starting with numbers or including spaces will be skipped.

    Further Reading

    This chapter covers what we believe to be the most useful of PHP's array functions. We have chosen not to cover all the possible array functions. The online PHP manual available at http://www.php.net has a brief description of each of them.

    Next

    In the next chapter, we look at string processing functions. We will cover functions that search, replace, split, and merge strings, as well as the powerful regular expression functions that can perform almost any action on a string.


     
     


    About The Perl ArchiveLink Validation ProcessSearch Tips
    Web Applications & Managed Hosting Powered by Gossamer Threads
    Visit our Mailing List Archives