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
The following is the definition of a two-dimensional array 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 you sort this array, in what order will the values appear? Because you know what the contents represent, there are at least two useful orders. You might want the products sorted into alphabetical order using the description or by numeric order by the price. Either result is possible, but you need to use the function usort() and tell PHP how to compare the items. To do this, you need to write your own comparison function.
The following code sorts this array into alphabetical order using the second column in the arraythe 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, you have called a number of the built-in PHP functions. To sort this array, you need to define a function of your own. We examine writing functions in detail in Chapter 5, "Reusing Code and Writing Functions," but here is a brief introduction.
You define a function by using the keyword function. You need to give the function a name. Names should be meaningful, so you can call it compare() for this example. Many functions take parameters or arguments. This 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 are two of the arrays within the main array, each representing one product. To access the Description of the array $x, you type $x[1] because the Description is the second element in these arrays, and numbering starts at zero. You use $x[1] and $y[1] to compare each Description from the arrays passed into the function.
When a function ends, it can give a reply to the code that called it. This process is called returning a value. To return a value, you use the keyword return in the 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, or a positive number if it is greater. The 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 you want sorted ($products) and the name of the comparison function (compare()).
If you want the array sorted into another order, you can simply write a different comparison function. To sort by price, you 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 is 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 user-defined comparison functions.
Similar to asort(), uasort() should be used when sorting a non-numerically indexed 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 a non-numerically indexed 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 sorts 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. Because you provide the comparison function, you can write a comparison function that returns the opposite values. To sort into reverse order, the function needs to return 1 if $x is less than $y and -1 if $x is greater than $y. For example,
function reverse_compare($x, $y) { if ( $x[2] == $y[2] ) return 0; else if ( $x[2] < $y[2] ) return 1; else return -1; }
Calling usort($products, 'reverse_compare') would now result in the array being placed in descending order by price.