Sporting more than 70 native array-related functions, PHP’s array manipulation capabilities have long been one of the language’s most attractive features. Whether you want to reverse an array, determine whether a value exists, convert an array to a string, or calculate the array size, completing the task is as simple as executing the appropriate function. There are however many array-related tasks which ask a bit more of the developer than merely knowing what part of the manual one needs to consult. Many such tasks require a somewhat more in-depth understanding of the native features, or are possible only when a bit of imagination is applied to the problem.
Sorting a Multidimensional Associative Array
PHP offers several array sorting functions, among them sort()
, ksort()
, and asort()
. But one feature seemingly missing is the ability to sort a multidimensional associative array such as the following:
Array
(
[0] => Array
(
[name] => chess
[price] => 12.99
)
[1] => Array
(
[name] => checkers
[price] => 9.99
)
[2] => Array
(
[name] => backgammon
[price] => 29.99
)
)
To sort the array by ascending price, you’ll need to create a function which compares each price, and then pass that function as a callback to the usort()
function:
function comparePrice($priceA, $priceB)
{
return $priceA['price'] - $priceB['price'];
}
usort($games, 'comparePrice');
After executing this snippet, the $games
array will be sorted like this:
Array
(
[0] => Array
(
[name] => checkers
[price] => 9.99
)
[1] => Array
(
[name] => chess
[price] => 12.99
)
[2] => Array
(
[name] => backgammon
[price] => 29.99
)
)
To sort the array in descending order, just update the comparePrice()
function to subtract $priceA['price']
from $priceB['price']
.
Iterating Recursively Over an Array
PHP’s while
and foreach
statements are the most common solution for iterating over an array. But how might you iterate over all contents of an array which looks like this:
Array
(
[0] => Array
(
[name] => Board
[games] => Array
(
[0] => Array
(
[name] => chess
[price] => 12.99
)
[1] => Array
(
[name] => checkers
[price] => 9.99
)
)
)
)
The Standard PHP Library‘s collection of iterators not only standardize the syntax used to iterate over a variety of different data structures (such as the file system and database results), but also takes much of the guesswork out of figuring out how to iterate over an unknown number of nested arrays. You can use the RecursiveArrayIterator to easily iterate over the above results:
$iterator = new RecursiveArrayIterator($games);
iterator_apply($iterator, 'navigateArray', array($iterator));
function navigateArray($iterator) {
while ($iterator->valid()) {
if ($iterator->hasChildren()) {
navigateArray($iterator->getChildren());
}
else {
printf("%s: %s
", $iterator->key(), $iterator->current());
}
$iterator->next();
}
}
Executing this snippet produces the following results:
name: Board
name: chess
price: 12.99
name: checkers
price: 9.99
Filtering Associative Array Results
Suppose you were handed the following array but only wanted to work with the games having a list price of less than $11.99
:
Array
(
[0] => Array
(
[name] => checkers
[price] => 9.99
)
[1] => Array
(
[name] => chess
[price] => 12.99
)
[2] => Array
(
[name] => backgammon
[price] => 29.99
)
)
Use the array_reduce()
function to create an array consisting solely of game names:
function filterGames($game)
{
return ($game['price'] < 11.99);
}
$names = array_filter($games, 'filterGames');
The array_filter()
function will filter out all array entries not satisfying a particular condition as determined by the callback function (which in this example is filterGames()
). Any game having a price of less than $11.99
is identified as a desirable entry, whereas the others are tossed aside. The outcome of executing this snippet follows:
Array
(
[1] => Array
(
[name] => checkers
[price] => 9.99
)
)
Converting an Object to an Array
The question of how to convert an object to an array often arises, and the answer is easier than many would think; just typecast the object! Consider the following example:
class Game {
public $name;
public $price;
}
$game = new Game();
$game->name = 'chess';
$game->price = 12.99;
print_r(array($game));
Executing this example produces the following output:
Array
(
[0] => Game Object
(
[name] => chess
[price] => 12.99
)
)
However, converting an object to an array has numerous initially unexpected side effects. For instance, the above snippet works fine if the properties are all public
, but private
properties are returned somewhat differently. Consider the following example:
class Game {
public $name;
private $_price;
public function setPrice($price)
{
$this->_price = $price;
}
}
$game = new Game();
$game->name = 'chess';
$game->setPrice(12.99);
print_r(array($game));
Executing this snippet produces the following output:
Array
(
[0] => Game Object
(
[name] => chess
[_price:Game:private] => 12.99
)
)
As you can see, the private price
property name is changed in the result in order to make clear the property is private.
Sorting an Array “Naturally”
Without a doubt one of the most confusing aspects of sorting an array is PHP’s unexpected approach to sorting alphanumeric strings. For instance, suppose you’ve expanded the gaming business into video games, and were creating a website which output dynamically generated video game covers in a certain order. The array looks like this:
Array
(
[0] => madden2011.png
[1] => madden2011-1.png
[2] => madden2011-2.png
[3] => madden2012.png
)
How would you expect this array to be sorted by PHP? Surprisingly, when using sort()
the output looks like this:
Array ( [0] => madden2011-1.png [1] => madden2011-2.png [2] => madden2011.png [3] => madden2012.png )
You can resolve this issue using the natsort()
function, which takes into account a “human”-oriented sorting perspective:
$prices = array('madden2011.png', 'madden2011-1.png',
'madden2011-2.png', 'madden2012.png');
sort($prices);
Execute this snippet and the array will look like this:
Array
(
[1] => madden2011-1.png
[2] => madden2011-2.png
[0] => madden2011.png
[3] => madden2012.png
)
Where to From Here?
PHP’s array iteration and manipulation capabilities are indeed profound, however the answers to some of the more advanced problems aren’t always so apparent; hopefully this article leaves you thinking about some of the approaches and behaviors you can exploit to sort even the most complex data structure!
Jason Gilmore is founder of the publishing, training, and consulting firm WJGilmore.com. He is the author of several popular books, including “Easy PHP Websites with the Zend Framework”, “Easy PayPal with PHP”, and “Beginning PHP and MySQL, Fourth Edition”. Follow him on Twitter at @wjgilmore.