Sorting an array of objects by one or more object property

Quite often I find myself having an array of objects and needing to sort that array of objects by property (either one property or multiple)…

Imagine, for example, getting a large result set from your database and ordering in the query just takes too long. Or perhaps you’re getting results from a web service and that service doesn’t return the results in the order you’d like to use. Have you ever found yourself in that situation, too? On looking at the usort documentation one day I came across a comment by someone called Will Shaver that did almost what I wanted. With a little adaptation for my own use (being able to change the sort order, for example), it has become one of my favourite functions to use for sorting.

loading gist...

Now a few cools things about the function:

  1. It uses anonymous/lambda functions (or closures, whatever your prefer to call them), and that’s just plain fun
  2. You can sort on more than one property and because the sorting is recursive, it’ll sort the second property within the confines of the first, the third within the confines of the second, and so on. Think sorting in SQL
  3. You can sort in ascending or descending order for any of the properties
  4. It retains key associations so you could use this on an associative array of objects
  5. If the parameter you want to sort on is an array itself then you can use any value (by specifying it’s key) in that array as the sorting value
Did you like this? Share it:

3 thoughts on “Sorting an array of objects by one or more object property

  1. Hello,

    Thank you for the sort function snippet it’s very handy!

    I’ve got a question.. Is it possible to sort an array of objects by objects’ property that is declared private? Or does the property have to be public?

    Many thanks,
    Dasha

  2. Hi Dasha – sorry about not responding earlier but I didn’t see your comment amongst the (seemingly) endless amounts of spam I get!

    No, I’m afraid you can’t sort by a private (or protected) property. Private properties are not accessible to code outside of the class, protected properties are only accessible to extending classes, so the osort function isn’t able to access them.

  3. I suppose, though, if you had private properties and set up the __get and __isset magic methods, then you could feasibly make it work. Consider this, for example:

    class Staff
    {
    	private $data = [
    		'name'   => null,
    		'email'  => null,
    		'age'    => null,
    		'salary' => null
    	];
    	
    	public function __construct($data)
    	{
    		$this->data['name']   = $data[0];
    		$this->data['email']  = $data[1];
    		$this->data['age']    = $data[2];
    		$this->data['salary'] = $data[3];
    	}
    	
    	public function __get($name)
    	{
    		return $this->data[$name];
    	}
    
    	public function __isset($name)
    	{
    		return !empty($this->data[$name]);
    	}
    }
    
    $test = [
    	['Foo', 'bar@example.com', 54, 63843],
    	['Joe', 'bloggs@example.org', 32, 20142],
    	['Anna', 'bananna@example.co.uk', 46, 42500]
    ];
    
    $default = [];
    foreach ($test as $t) {
    	$default[] = new Staff($t);
    }
    
    echo "Default\n\n";
    var_dump($default);
    
    foreach (['name', 'email', 'age', 'salary'] as $prop) {
    	$staff = $default;
    	echo "\nBy {$prop}\n\n";
    	osort($staff, [$prop]);
    	var_dump($staff);
    	echo "\n\n";
    }
    
    

    That’d end up sorting everything correctly even though the data in the objects is private.

Leave a Reply