The function to sort multidimensional array by value
function array_multiorderby( $data, $orderby, $children_key=false ) { // parsing orderby $args = array(); $x = explode( ' ', str_replace( ',', ' ', $orderby ) ); foreach( $x as $item ) { $item = trim( $item ); if( $item=='' ) continue; if( strtolower($item)=='asc' ) $item = SORT_ASC; else if( strtolower($item)=='desc' ) $item = SORT_DESC; $args[] = $item; } // order foreach ($args as $n => $field) { if (is_string($field)) { $tmp = array(); foreach ($data as $key => $row) $tmp[$key] = $row[$field]; $args[$n] = $tmp; } } $args[] = &$data; call_user_func_array('array_multisort', $args); $data = array_pop($args); // order children if( $children_key ) { foreach( $data as $k=>$v ) if( is_array($v[$children_key]) ) { $data[$k][$children_key] = array_multiorderby( $v[$children_key], $orderby, $children_key ); } } // return return $data; }
Arguments
This function accepts three arguments:
-
ARRAY $data
The input array that we want to order.
-
STRING $orderby
A SQL-like “orderby” clause. Example: “column_name ASC,column_name DESC”.
-
STRING $children_key
The associative key used for defining eventual children of a node.
Return
The function returns a sorted array.
Example
Define some data
To see the function in action let’s create an opportune array first of all:
$data = array( 'node1' => array( 'title'=>"Node 1", 'weight'=>'31' ), 'node2' => array( 'title'=>"Node 2", 'weight'=>'33', 'children' => array( 'node2_1' => array( 'title'=>"Child Node 2_1", 'weight'=>'25' ), 'node2_2' => array( 'title'=>"Child Node 2_1", 'weight'=>'27', 'children' => array( 'node2_2_1' => array( 'title'=>"Child Node 2_2_1", 'weight'=>'18' ), 'node2_2_2' => array( 'title'=>"Child Node 2_2_2", 'weight'=>'15' ), 'node2_2_3' => array( 'title'=>"Child Node 2_2_3_A", 'weight'=>'10' ), 'node2_2_4' => array( 'title'=>"Child Node 2_2_3_F", 'weight'=>'10' ), 'node2_2_5' => array( 'title'=>"Child Node 2_2_3_C", 'weight'=>'10' ), 'node2_2_6' => array( 'title'=>"Child Node 2_2_3_E", 'weight'=>'10' ), 'node2_2_7' => array( 'title'=>"Child Node 2_2_3_D", 'weight'=>'10' ), 'node2_2_8' => array( 'title'=>"Child Node 2_2_3_B", 'weight'=>'10' ), ) ), 'node2_3' => array( 'title'=>"Child Node 2_1", 'weight'=>'56' ), 'node2_4' => array( 'title'=>"Child Node 2_1", 'weight'=>'50' ), 'node2_5' => array( 'title'=>"Child Node 2_1", 'weight'=>'24' ), ) ), 'node3' => array( 'title'=>"Node 3", 'weight'=>'32' ), 'node4' => array( 'title'=>"Node 4", 'weight'=>'160' ), 'node5' => array( 'title'=>"Node 5", 'weight'=>'3' ), );
This array could be represented as follow:
Node 1 (weight:31) Node 2 (weight:33) Node 2_1 (weight:25) Node 2_2 (weight:27) Node 2_2_1 (weight:18) Node 2_2_2 (weight:15) Node 2_2_3_A (weight:10) Node 2_2_3_F (weight:10) Node 2_2_3_C (weight:10) Node 2_2_3_E (weight:10) Node 2_2_3_D (weight:10) Node 2_2_3_B (weight:10) Node 2_3 (weight:56) Node 2_4 (weight:50) Node 2_5 (weight:24) Node 3 (weight:32) Node 4 (weight:160) Node 5 (weight:3)
Apply the function
Now let’s apply the function. To make the things harder, we will try to order the array by the weight and title.
$newdata = array_multiorderby( $data, "weight asc, title desc", 'children' );
Here is the output
The new array will be:
Node 5 (weight:3) Node 1 (weight:31) Node 3 (weight:32) Node 2 (weight:33) Node 2_5 (weight:24) Node 2_1 (weight:25) Node 2_2 (weight:27) Node 2_2_3_F (weight:10) Node 2_2_3_E (weight:10) Node 2_2_3_D (weight:10) Node 2_2_3_C (weight:10) Node 2_2_3_B (weight:10) Node 2_2_3_A (weight:10) Node 2_2_2 (weight:15) Node 2_2_1 (weight:18) Node 2_4 (weight:50) Node 2_3 (weight:56) Node 4 (weight:160)
As you can see, all the elements are ordered by weight (asc) and just after, by title (desc).
The complete script
You can download the whole script (that include the example also) just click the link below.
Download the Function + Example
Hope this helps
I hope you have found useful my solution.
If you have encountered some problems, please let me know.
If you have a smarter solution to sort multidimensional array by value please add a comment below.
Bye!