PHPの配列を複数項目でソートする

SQLの　「order by」と同じ挙動で複数項目でソートする

```php
$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);
```

```php
<?

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/niiyz/PHP-OrderBy


参考:
https://github.com/laravel/framework/blob/5.8/src/Illuminate/Support/Collection.php#L1650-L1659
https://atuweb.net/201611_laravel-sort-by-multiple-columns/