Sort multidimensional array by multiple columns
You need array_multisort
$mylist = array(
array('ID' => 1, 'title' => 'Boring Meeting', 'event_type' => 'meeting'),
array('ID' => 2, 'title' => 'Find My Stapler', 'event_type' => 'meeting'),
array('ID' => 3, 'title' => 'Mario Party', 'event_type' => 'party'),
array('ID' => 4, 'title' => 'Duct Tape Party', 'event_type' => 'party')
);
# get a list of sort columns and their data to pass to array_multisort
$sort = array();
foreach($mylist as $k=>$v) {
$sort['title'][$k] = $v['title'];
$sort['event_type'][$k] = $v['event_type'];
}
# sort by event_type desc and then title asc
array_multisort($sort['event_type'], SORT_DESC, $sort['title'], SORT_ASC,$mylist);
As of PHP 5.5.0:
array_multisort(array_column($mylist, 'event_type'), SORT_DESC,
array_column($mylist, 'title'), SORT_ASC,
$mylist);
$mylist
is now:
array (
0 =>
array (
'ID' => 4,
'title' => 'Duct Tape Party',
'event_type' => 'party',
),
1 =>
array (
'ID' => 3,
'title' => 'Mario Party',
'event_type' => 'party',
),
2 =>
array (
'ID' => 1,
'title' => 'Boring Meeting',
'event_type' => 'meeting',
),
3 =>
array (
'ID' => 2,
'title' => 'Find My Stapler',
'event_type' => 'meeting',
),
)
PHP7 Makes sorting by multiple columns SUPER easy with the spaceship operator (<=>
) aka the "Combined Comparison Operator" or "Three-way Comparison Operator".
Resource: https://wiki.php.net/rfc/combined-comparison-operator
Sorting by multiple columns is as simple as writing balanced/relational arrays on both sides of the operator. Easy done!
When the $a
value is on the left of the spaceship operator and the $b
value is on the right, ASCending sorting is used.
When the $b
value is on the left of the spaceship operator and the $a
value is on the right, DESCending sorting is used.
When the spaceship operator compares two numeric strings, it compares them as numbers -- so you get natural sorting automagically.
I have not used uasort()
because I don't see any need to preserve the original indexes.
Code: (Demo) -- sorts by state
ASC, then event_type
ASC, then date_start
ASC
$array = [
['ID' => 1, 'title' => 'Boring Meeting', 'date_start' => '2010-07-30', 'event_type' => 'meeting', 'state' => 'new-york'],
['ID' => 2, 'title' => 'Find My Stapler', 'date_start' => '2010-07-22', 'event_type' => 'meeting', 'state' => 'new-york'],
['ID' => 3, 'title' => 'Mario Party', 'date_start' => '2010-07-22', 'event_type' => 'party', 'state' => 'new-york'],
['ID' => 4, 'title' => 'Duct Tape Party', 'date_start' => '2010-07-28', 'event_type' => 'party', 'state' => 'california']
];
usort($array, function($a, $b) {
return [$a['state'], $a['event_type'], $a['date_start']]
<=>
[$b['state'], $b['event_type'], $b['date_start']];
});
var_export($array);
Output
array (
0 =>
array (
'ID' => 4,
'title' => 'Duct Tape Party',
'date_start' => '2010-07-28',
'event_type' => 'party',
'state' => 'california',
),
1 =>
array (
'ID' => 2,
'title' => 'Find My Stapler',
'date_start' => '2010-07-22',
'event_type' => 'meeting',
'state' => 'new-york',
),
2 =>
array (
'ID' => 1,
'title' => 'Boring Meeting',
'date_start' => '2010-07-30',
'event_type' => 'meeting',
'state' => 'new-york',
),
3 =>
array (
'ID' => 3,
'title' => 'Mario Party',
'date_start' => '2010-07-22',
'event_type' => 'party',
'state' => 'new-york',
),
)
p.s. Arrow syntax with PHP7.4 and higher (Demo)...
usort($array, fn($a, $b) =>
[$a['state'], $a['event_type'], $a['date_start']]
<=>
[$b['state'], $b['event_type'], $b['date_start']]
);
The equivalent technique with array_multisort()
and a call of array_column()
for every sorting criteria is: (Demo)
array_multisort(
array_column($array, 'state'),
array_column($array, 'event_type'),
array_column($array, 'date_start'),
$array
);