SQLの 「order by」と同じ挙動で複数項目でソートする
$products = [
['month' => '2020/01/01', 'key1' => 1, 'key2' => 1, 'key3' => 1, 'key4' => 1, 'key5' => 1, 'id' => 1],
['month' => '2017/01/01', 'key1' => 1, 'key2' => 1, 'key3' => 1, 'key4' => 1, 'key5' => 2, 'id' => 2],
['month' => '2017/01/01', 'key1' => 1, 'key2' => 1, 'key3' => 1, 'key4' => 2, 'key5' => 3, 'id' => 3],
['month' => '2017/01/01', 'key1' => 3, 'key2' => 3, 'key3' => 3, 'key4' => 3, 'key5' => 1, 'id' => 4],
['month' => '2017/01/01', 'key1' => 1, 'key2' => 1, 'key3' => 1, 'key4' => 1, 'key5' => 1, 'id' => 5],
['month' => '2017/01/01', 'key1' => 2, 'key2' => 2, 'key3' => 1, 'key4' => 1, 'key5' => 2, 'id' => 6],
['month' => '2017/01/01', 'key1' => 1, 'key2' => 4, 'key3' => 1, 'key4' => 2, 'key5' => 3, 'id' => 7],
['month' => '2017/01/01', 'key1' => 1, 'key2' => 1, 'key3' => 2, 'key4' => 1, 'key5' => 2, 'id' => 8],
['month' => '2018/01/01', 'key1' => 1, 'key2' => 1, 'key3' => 1, 'key4' => 1, 'key5' => 1, 'id' => 9],
];
$sort = ['month desc', 'key1 desc', 'key2', 'key3', 'key4', 'key5'];
$sortedProducts = orderBy($products, $sort);
$this->assertEquals([
['month' => '2020/01/01', 'key1' => 1, 'key2' => 1, 'key3' => 1, 'key4' => 1, 'key5' => 1, 'id' => 1],
['month' => '2018/01/01', 'key1' => 1, 'key2' => 1, 'key3' => 1, 'key4' => 1, 'key5' => 1, 'id' => 9],
['month' => '2017/01/01', 'key1' => 3, 'key2' => 3, 'key3' => 3, 'key4' => 3, 'key5' => 1, 'id' => 4],
['month' => '2017/01/01', 'key1' => 2, 'key2' => 2, 'key3' => 1, 'key4' => 1, 'key5' => 2, 'id' => 6],
['month' => '2017/01/01', 'key1' => 1, 'key2' => 1, 'key3' => 1, 'key4' => 1, 'key5' => 1, 'id' => 5],
['month' => '2017/01/01', 'key1' => 1, 'key2' => 1, 'key3' => 1, 'key4' => 1, 'key5' => 2, 'id' => 2],
['month' => '2017/01/01', 'key1' => 1, 'key2' => 1, 'key3' => 1, 'key4' => 2, 'key5' => 3, 'id' => 3],
['month' => '2017/01/01', 'key1' => 1, 'key2' => 1, 'key3' => 2, 'key4' => 1, 'key5' => 2, 'id' => 8],
['month' => '2017/01/01', 'key1' => 1, 'key2' => 4, 'key3' => 1, 'key4' => 2, 'key5' => 3, 'id' => 7],
], $sortedProducts);
<?
function orderBy(array $items, array $sortItems)
{
$orders = [];
foreach ($sortItems as $sortItem) {
$orders[] = explode(' ', $sortItem);
}
$equal = function ($first, $second, $orders, $max) {
for ($i = 0; $i < $max;$i ++) {
if ($first[$orders[$i][0]] !== $second[$orders[$i][0]]) {
return false;
}
}
return $first[$orders[$max][0]] < $second[$orders[$max][0]] ? ($orders[$max][1] === 'desc' ? 1 : -1) : ($orders[$max][1] === 'desc' ? -1 : 1);
};
$callback = function($first, $second) use($orders, $equal) {
for ($i = count($orders) - 1;$i >= 0;$i --) {
$result = $equal($first, $second, $orders, $i);
if ($result !== false) {
return $result;
}
}
};
uasort($items, $callback);
return array_values($items);
}
参考:
https://github.com/laravel/framework/blob/5.8/src/Illuminate/Support/Collection.php#L1650-L1659
https://atuweb.net/201611_laravel-sort-by-multiple-columns/