Sorting an array of objects in PHP

posted on: 2010-06-06 22:49:35




Today I thought that I would talk about using a comparison delegate function with native PHP sort functions. The reason for me writing this tutorial is that I often come across code where developers have needlessly tried to sort arrays of objects using some pretty elaborate means. Native PHP functions usort, uksort and uasort take a secondary parameter of a callback function where you can specify the logic of how the comparison will take place. You may either pass a string value of the comparison function name or you can pass an array representing class structure relative to the function, as I will use in my example.

Here is a reasonably simple class. Nothing special and pretty ordinary.

class Item
{	
	var $name;
	var $price;
	var $order;
	
	function __construct($_name, $_price, $_order)
	{
		$this->name = $_name;
		$this->price = $_price;
		$this->order = $_order;
	}
}

Now I am going to create a sorter class to handle the sorting and comparison of my item class. Comparison delegate functions should take two parameters. The comparison delegate function will be passed two variables to compare, the function must then return an integer representing the relationship of the first parameter against the second. Less than zero if it is less, Zero if they are equal and a value greater than zero if it is the greater.

I have kept my comparison class very simple with three delegate functions. These functions call one single function that handles the comparison depending on the name of the child variable of the item class which is passed as a string parameter.

class ItemSorter
{
	function ComparisonDelegateByOrder($a, $b)
	{
		return self::ComparisonDelegate($a, $b, "order");
	}
	
	function ComparisonDelegateByName($a, $b)
	{
		return self::ComparisonDelegate($a, $b, "name");
	}
	
	function ComparisonDelegateByPrice($a, $b)
	{
		return self::ComparisonDelegate($a, $b, "price");
	}
	
	function ComparisonDelegate($a, $b, $field)
	{
		if ($a->$field == $b->$field) {
			return 0;
		}
		return ($a->$field < $b->$field) ? -1 : 1;
	}

}

Now I create an array of my Item class. I then use the usort function to sort the array using the delegate functions. I have also created a function to print out the sorted arrays in their respective orders.

$arrayOfItems = array(
	new Item ("Glass", 3.44, 4),
	new Item ("Cup", 10.43, 2),
	new Item ("Plate", 9.02, 3),
	new Item ("Fork", 0.10, 1),
	new Item ("Spoon", 34.87, 5)
	);
	
usort($arrayOfItems, array("ItemSorter", "ComparisonDelegateByOrder"));
PrintItemArray($arrayOfItems, "ComparisonDelegateByOrder");

usort($arrayOfItems, array("ItemSorter", "ComparisonDelegateByName"));
PrintItemArray($arrayOfItems, "ComparisonDelegateByName");

usort($arrayOfItems, array("ItemSorter", "ComparisonDelegateByPrice"));
PrintItemArray($arrayOfItems, "ComparisonDelegateByPrice");


function PrintItemArray($arrayOfItems, $delegateName)
{
	echo "****************** $delegateName **********************";
	foreach ($arrayOfItems as $key => $value) {
		echo "<pre>";
		print_r($value);
		echo "</pre>";
	}
}
The source for this tutorial is available here custom_sort.php.txt