We have the follow data:
Last name | First name |
---|---|
Petrova | Sveta |
Ivanov | Oleg |
Petrova | Anna |
Ivanov | Ivan |
We need to sort it by last name and first name in ascending order. How to do that by using PHP? array_multisort
will help to us!
More info about
array_multisort
: https://www.php.net/manual/en/function.array-multisort.php
$data = [
['Petrova', 'Sveta'],
['Ivanov', 'Oleg'],
['Petrova', 'Anna'],
['Ivanov', 'Ivan'],
];
$lastNames = array_column($data, 0);
$firstNames = array_column($data, 1);
// This fix is used for cases when main sorting specified by columns has equal values
// Without it it will lead to Fatal Error: Nesting level too deep - recursive dependency?
// Thanks to Yii community https://github.com/yiisoft/yii2/issues/8348
$indexes = range(1, count($data));
array_multisort(
$lastNames,
SORT_ASC,
SORT_STRING,
$firstNames,
SORT_ASC,
SORT_STRING,
$indexes,
SORT_ASC,
SORT_NUMERIC,
$data
);
Result:
Last name | First name |
---|---|
Ivanov | Ivan |
Ivanov | Oleg |
Petrova | Anna |
Petrova | Sveta |
This example is simple, and we didn't use descending order. Let's sort last name in ascending order and first name in descending order.
array_multisort(
$lastNames,
SORT_ASC,
SORT_STRING,
$firstNames,
SORT_DESC,
SORT_STRING,
$indexes,
SORT_ASC,
SORT_NUMERIC,
$data
);
Result:
Last name | First name |
---|---|
Ivanov | Oleg |
Ivanov | Ivan |
Petrova | Sveta |
Petrova | Anna |
By the way, we might don't use array_multisort
. Below I show multisort without the "magic" function (thanks to Doctrine community).
$data = [
['Petrova', 'Sveta'],
['Ivanov', 'Oleg'],
['Petrova', 'Anna'],
['Ivanov', 'Ivan'],
];
$orderings = [
'lastName' => SORT_ASC,
'firstName' => SORT_DESC,
];
$orderFn = null;
foreach (array_reverse($orderings) as $field => $ordering) {
$orderFn = function (array $a, array $b) use ($orderFn, $field, $ordering): int {
switch ($field) {
case 'lastName':
$column = 0;
break;
case 'firstName':
$column = 1;
break;
default:
return 0;
}
if ($a[$column] === $b[$column]) {
if ($orderFn !== null) {
return $orderFn($a, $b);
} else {
return 0;
}
}
return ($a[$column] <=> $b[$column]) * ($ordering === SORT_ASC ? 1 : -1);
};
}
uasort($data, $orderFn);
Result:
Last name | First name |
---|---|
Ivanov | Oleg |
Ivanov | Ivan |
Petrova | Sveta |
Petrova | Anna |