| Programming PHP
Chapter 5: Arrays By Kevin Tatroe and Rasmus Lerdorf
Download the code examples from this book As we discussed in Chapter 2, PHP supports both scalar and compound data types. In this chapter, we'll discuss one of the compound types: arrays. An array is a collection of data values, organized as an ordered collection of key-value pairs. This chapter talks about creating an array, adding and removing elements from an array, and looping over the contents of an array. There are many built-in functions that work with arrays in PHP, because arrays are very common and useful. For example, if you want to send email to more than one email address, you'll store the email addresses in an array and then loop through the array, sending the message to the current email address. Also, if you have a form that permits multiple selections, the items the user selected are returned in an array. Indexed Versus Associative ArraysThere are two kinds of arrays in PHP: indexed and associative. The keys of an indexed array are integers, beginning at 0. Indexed arrays are used when you identify things by their position. Associative arrays have strings as keys and behave more like two-column tables. The first column is the key, which is used to access the value. PHP internally stores all arrays as associative arrays, so the only difference between associative and indexed arrays is what the keys happen to be. Some array features are provided mainly for use with indexed arrays, because they assume that you have or want keys that are consecutive integers beginning at 0. In both cases, the keys are unique--that is, you can't have two elements with the same key, regardless of whether the key is a string or an integer. PHP arrays have an internal order to their elements that is independent of the keys and values, and there are functions that you can use to traverse the arrays based on this internal order. The order is normally that in which values were inserted into the array, but the sorting functions described later let you change the order to one based on keys, values, or anything else you choose. Identifying Elements of an ArrayYou can access specific values from an array using the array variable's name, followed by the element's key (sometimes called the index) within square brackets:
The key can be either a string or an integer. String values that are equivalent to integer numbers (without leading zeros) are treated as integers. Thus,
$array[3] and
$array['3'] reference the same element, but
$array['03'] references a different element. Negative numbers are valid keys, and they don't specify positions from the end of the array as they do in Perl.
You don't have to quote single-word strings. For instance,
$age['Fred'] is the same as
$age[Fred]. However, it's considered good PHP style to always use quotes, because quoteless keys are indistinguishable from constants. When you use a constant as an unquoted index, PHP uses the value of the constant as the index:
You must use quotes if you're using interpolation to build the array index:
However, don't quote the key if you're interpolating an array lookup:
Storing Data in Arrays
Storing a value in an array will create the array if it didn't already exist, but trying to retrieve a value from an array that hasn't been defined yet won't create the array. For example:
Using simple assignment to initialize an array in your program leads to code like this:
That's an indexed array, with integer indexes beginning at 0. Here's an associative array:
An easier way to initialize an array is to use the
array( ) construct, which builds an array from its arguments:
To create an associative array with
array( ), use the
=> symbol to separate indexes from values:
Notice the use of whitespace and alignment. We could have bunched up the code, but it wouldn't have been as easy to read:
To construct an empty array, pass no arguments to
array( ):
You can specify an initial key with
=> and then a list of values. The values are inserted into the array starting with that key, with subsequent values having sequential keys:
If the initial index is a non-numeric string, subsequent indexes are integers beginning at 0. Thus, the following code is probably a mistake:
Adding Values to the End of an Array
To insert more values into the end of an existing indexed array, use the
This construct assumes the array's indexes are numbers and assigns elements into the next available numeric index, starting from 0. Attempting to append to an associative array is almost always a programmer mistake, but PHP will give the new elements numeric indexes without issuing a warning:
Assigning a Range of Values
The
Only the first letter of a string argument is used to build the range:
Getting the Size of an Array
The
These functions do not consult any numeric indexes that might be present:
Padding an Array
To create an array initialized to the same value, use
array_pad( ) in action:
Notice how the new values are appended to the end of the array. If you want the new values added to the start of the array, use a negative second argument:
Assign the results of
array_pad( ) back to the original array to get the effect of an in situ change:
If you pad an associative array, existing keys will be preserved. New elements will have numeric keys starting at 0.
Multidimensional Arrays
The values in an array can themselves be arrays. This lets you easily create multidimensional arrays:
You can refer to elements of multidimensional arrays by appending more
[]s:
To interpolate a lookup of a multidimensional array, you must enclose the entire array lookup in curly braces:
Failing to use the curly braces results in output like this:
Extracting Multiple Values
To copy all of an array's values into variables, use the
The array's values are copied into the listed variables, in the array's internal order. By default that's the order in which they were inserted, but the sort functions described later let you change that. Here's an example:
If you have more values in the array than in the
list( ), the extra values are ignored:
If you have more values in the
list( ) than in the array, the extra values are set to
NULL:
Two or more consecutive commas in the
list( ) skip values in the array:
Slicing an Array
To extract only a subset of the array, use the
The
array_slice( ) function returns a new array consisting of a consecutive series of values from the original array. The
offset parameter identifies the initial element to copy (
0 represents the first element in the array), and the
length parameter identifies the number of values to copy. The new array has consecutive numeric keys starting at 0. For example:
It is generally only meaningful to use
array_slice( ) on indexed arrays (i.e., those with consecutive integer indexes, starting at 0):
Combine
array_slice( ) with
list( ) to extract only some values to variables:
Splitting an Array into Chunks
To divide an array into smaller, evenly sized arrays, use the
The function returns an array of the smaller arrays. The third argument,
preserve_keys, is a Boolean value that determines whether the elements of the new arrays have the same keys as in the original (useful for associative arrays) or new numeric keys starting from 0 (useful for indexed arrays). The default is to assign new keys, as shown here:
Keys and Values
The
Here's an example:
PHP also provides a (less generally useful) function to retrieve an array of just the values in an array,
array_values( ):
As with
array_keys( ), the values are returned in the array's internal order:
Checking Whether an Element Exists
To see if an element exists in the array, use the
The function returns a Boolean value that indicates whether the second argument is a valid key in the array given as the first argument.
It's not sufficient to simply say:
Even if there is an element in the array with the key
name, its corresponding value might be false (i.e., 0,
NULL, or the empty string). Instead, use
array_key_exists( ) as follows:
In PHP 4.0.6 and earlier versions, the
array_key_exists( ) function was called
key_exists( ). The original name is still retained as an alias for the new name.
Many people use the
isset( ) function instead, which returns
true if the element exists and is not
NULL:
Removing and Inserting Elements in an Array
The
We'll look at
array_splice( ) using this array:
We can remove the
math,
bio, and
cs elements by telling
array_splice( ) to start at position 2 and remove 3 elements:
If you omit the length,
array_splice( ) removes to the end of the array:
If you simply want to delete the elements and you don't care about their values, you don't need to assign the results of
array_splice( ):
To insert elements where others were removed, use the fourth argument:
The size of the replacement array doesn't have to be the same as the number of elements you delete. The array grows or shrinks as needed:
To get the effect of inserting new elements into the array, delete zero elements:
Although the examples so far have used an indexed array,
array_splice( ) also works on associative arrays:
Converting Between Arrays and Variables
PHP provides two functions,
can be converted to, or built from, these variables:
Creating Variables from an Array
The
If a variable created by the extraction has the same name as an existing one, the extracted variable overwrites the existing variable.
You can modify
extract( )'s behavior by passing a second argument. Appendix A describes the possible values for this second argument. The most useful value is
EXTR_PREFIX_SAME, which says that the third argument to
extract( ) is a prefix for the variable names that are created. This helps ensure that you create unique variable names when you use
extract( ). It is good PHP style to always use
EXTR_PREFIX_SAME, as shown here:
Creating an Array from Variables
The
Traversing Arrays
The 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. The foreach Construct The most common way to loop over elements of an array is to use the
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:
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.
The Iterator Functions
Every 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:
each( ) function is used to loop over the elements of an array. It processes elements according to their internal order:
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
Using a for Loop
If you know that you are dealing with an indexed array, where the keys are consecutive integers beginning at 0, you can use a
for:
Calling a Function for Each Array Element
PHP provides a mechanism,
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:
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:
The
array_walk( ) function processes elements in their internal order.
Reducing an Array
A cousin of
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:
The
array_reduce( ) line makes these function calls:
The
default argument, if provided, is a seed value. For instance, if we change the call to
array_reduce( ) in the previous example to:
The resulting function calls are:
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.
Searching for Values
The
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:
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
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:
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.
Sorting
Sorting changes the internal order of elements in an array and optionally rewrites the keys to reflect this new order. For example, you might use sorting to arrange a list of scores from biggest to smallest, to alphabetize a list of names, or to order a set of users based on how many messages they posted. PHP provides three ways to sort arrays--sorting by keys, sorting by values without changing the keys, or sorting by values and then changing the keys. Each kind of sort can be done in ascending order, descending order, or an order defined by a user-defined function. Sorting One Array at a TimeThe functions provided by PHP to sort an array are shown in Table 5-1. The sort( ),
rsort( ), and
usort( ) functions are designed to work on indexed arrays, because they assign new numeric keys to represent the ordering. They're useful when you need to answer questions like "what are the top 10 scores?" and "who's the third person in alphabetical order?" The other sort functions can be used on indexed arrays, but you'll only be able to access the sorted ordering by using traversal functions such as
foreach and
next.
To sort names into ascending alphabetical order, you'd use this:
To get them in reverse alphabetic order, simply call
rsort( ) instead of
sort( ).
If you have an associative array mapping usernames to minutes of login time, you can use
arsort( ) to display a table of the top three, as shown here:
If you want that table displayed in ascending order by username, use
ksort( ):
User-defined ordering requires that you provide a function that takes two values and returns a value that specifies the order of the two values in the sorted array. The function should return
1 if the first value is greater than the second,
-1 if the first value is less than the second, and
0 if the values are the same for the purposes of your custom sort order.
Example 5-3 is a program that lets you try the various sorting functions on the same data.
Natural-Order Sorting
PHP's built-in sort functions correctly sort strings and numbers, but they don't correctly sort strings that contain numbers. For example, if you have the filenames
ex10.php,
ex5.php, and
ex1.php, the normal sort functions will rearrange them in this order:
ex1.php,
ex10.php,
ex5.php. To correctly sort strings that contain numbers, use the
Sorting Multiple Arrays at Once
The
Pass it a series of arrays and sorting orders (identified by the
SORT_ASC or
SORT_DESC constants), and it reorders the elements of all the arrays, assigning new indexes. It is similar to a join operation on a relational database.
Imagine that you have a lot of people, and several pieces of data on each person:
The first element of each array represents a single record--all the information known about Tom. Similarly, the second element constitutes another record--all the information known about Dick. The
array_multisort( ) function reorders the elements of the arrays, preserving the records. That is, if
Dick ends up first in the
$names array after the sort, the rest of Dick's information will be first in the other arrays too. (Note that we needed to quote Dick's zip code to prevent it from being interpreted as an octal constant.)
Here's how to sort the records first ascending by age, then descending by zip code:
We need to include
$names in the function call to ensure that Dick's name stays with his age and zip code. Printing out the data shows the result of the sort:
Reversing Arrays
The
Numeric keys are renumbered starting at 0, while string indexes are unaffected. In general, it's better to use the reverse-order sorting functions instead of sorting and then reversing the order of an array.
The
array_flip( ) function returns an array that reverses the order of each original element's key-value pair:
That is, for each element of the array whose value is a valid key, the element's value becomes its key and the element's key becomes its value. For example, if you have an array mapping usernames to home directories, you can use
array_flip( ) to create an array mapping home directories to usernames:
Elements whose original values are neither strings nor integers are left alone in the resulting array. The new array lets you discover the key in the original array given its value, but this technique works effectively only when the original array has unique values.
Randomizing Order
To traverse the elements in an array in a random order, use the
Obviously, the order after your
shuffle( ) may not be the same as the sample output here. Unless you are interested in getting multiple random elements from an array, without repeating any specific item, using the
rand( ) function to pick an index is more efficient.
Acting on Entire Arrays
PHP has several useful functions for modifying or applying an operation to all elements of an array. You can merge arrays, find the difference, calculate the total, and more, all using built-in functions. Calculating the Sum of an Array The
For example:
Merging Two Arrays
The
If a numeric key from an earlier array is repeated, the value from the later array is assigned a new numeric key:
If a string key from an earlier array is repeated, the earlier value is replaced by the later value:
Calculating the Difference Between Two Arrays
The
For example:
Values are compared using
===, so
1 and
"1" are considered different. The keys of the first array are preserved, so in
$diff the key of
'bill' is 0 and the key of
'judy' is 4.
Filtering Elements from an Array
To identify a subset of an array based on its values, use the
Each value of
array is passed to the function named in
callback. The returned array contains only those elements of the original array for which the function returns a
true value. For example:
As you see, the keys are preserved. This function is most useful with associative arrays.
Using Arrays
Arrays crop up in almost every PHP program. In addition to their obvious use for storing collections of values, they're also used to implement various abstract data types. In this section, we show how to use arrays to implement sets and stacks. SetsArrays let you implement the basic operations of set theory: union, intersection, and difference. Each set is represented by an array, and various PHP functions implement the set operations. The values in the set are the values in the array--the keys are not used, but they are generally preserved by the operations. The union of two sets is all the elements from both sets, with duplicates removed. Thearray_merge( ) and
array_unique( ) functions let you calculate the union. Here's how to find the union of two arrays:
The
intersection of two sets is the set of elements they have in common. PHP's built-in
array_intersect( ) function takes any number of arrays as arguments and returns an array of those values that exist in each. If multiple keys have the same value, the first key with that value is preserved.
Another common function to perform on a set of arrays is to get the
difference; that is, the values in one array that are not present in another array. The
array_diff( ) function calculates this, returning an array with values from the first array that are not present in the second.
The following code takes the difference of two arrays:
Stacks
Although not as common in PHP programs as in other programs, one fairly common data type is the last-in first-out (LIFO) stack. We can create stacks using a pair of PHP functions,
Here's the output from
Example 5-4:
|
