Laravelのソート操作：usort、sortBy、orderByの違い

Laravelでは、データの並べ替え（ソート）を行うためのいくつかの方法があります。
- PHPのusort関数
- Laravel独自のsortByメソッド
- クエリビルダのorderByメソッド

本記事では、それぞれの使い所を紹介します。

## usortとは？
usortは、PHPの組み込み関数であり、ユーザー定義の比較関数に基づいて配列をソートするために使用されます。シンプルなソートから複雑なカスタムロジックに基づくソートまで、柔軟に対応できるのが特徴です。

### usortの基本的な使い方
```php
usort($array, 'callback');
```

- **$array:** ソート対象の配列、usortはこの配列を直接変更します
- **'callback':** 2つの要素を比較するためのユーザー定義の比較関数。この関数は次の値を返します:
    - 負の整数（$a < $b の場合）
    - 正の整数（$a > $b の場合）
    - 0（$a == $b の場合）
### usortを使った例
配列内のオブジェクトを特定のプロパティでソートする例です。
```php
$items = [
    ['name' => 'John', 'age' => 30],
    ['name' => 'Jane', 'age' => 25],
    ['name' => 'Doe', 'age' => 35],
];

usort($items, function($a, $b) {
    return $a['age'] <=> $b['age'];
});

print_r($items);
```
```
Array
(
    [0] => Array
        (
            [name] => Jane
            [age] => 25
        )

    [1] => Array
        (
            [name] => John
            [age] => 30
        )

    [2] => Array
        (
            [name] => Doe
            [age] => 35
        )
)
```

- <=> 演算子（スペースシップ演算子）は、2つの値を比較して-1、0、1を返します
- この例では、ageの値に基づいてユーザーを昇順にソートしています


### Laravelでの使用シナリオ
主に以下のようなケースで使用します：
- **カスタムロジックが必要な場合:** データベースクエリでは実現しにくい複雑なソート条件がある場合
- **配列データの操作:** 外部APIから取得したデータや、Eloquentモデルを配列に変換した後にソートを行いたい場合



### Eloquentモデルとusortの例
LaravelのEloquentで取得したデータをPHPで並べ替える場合、usortを以下のように使用できます。

```php
$users = User::all()->toArray();

usort($users, function($a, $b) {
    // カスタムロジック: 年齢が同じ場合は名前でソート
    if ($a['age'] === $b['age']) {
        return strcmp($a['name'], $b['name']);
    }
    return $a['age'] <=> $b['age'];
});

print_r($users);
```
この例では、まず年齢で昇順にソートし、年齢が同じ場合は名前でアルファベット順にソートしています。


## sortByとは？

sortByは、Laravelのコレクションで使用できるメソッドで、特定のキーやコールバックに基づいてソートします。usortと異なり、元のコレクションを変更せずに新しいソート済みのコレクションを返すため、メソッドチェーンを続けることができます。

### sortByの基本的な使い方
```php
collect($array)->sortBy($key);
```

- **$key:** ソート基準となるキー名やコールバック関数

### sortByを使った例

```php
$users = collect([
    ['name' => 'John', 'age' => 30],
    ['name' => 'Jane', 'age' => 25],
    ['name' => 'Doe', 'age' => 35],
]);

$sortedUsers = $users->sortBy('age');

$sortedUsers->all();
```

```
[
    ['name' => 'Jane', 'age' => 25],
    ['name' => 'John', 'age' => 30],
    ['name' => 'Doe', 'age' => 35],
]
```

- collect()関数で配列をコレクションに変換し、sortBy('age')でageキーに基づいて昇順にソートしています。
- 結果は新しいコレクションとして返されるため、元の$usersコレクションは変更されません。



### カスタムロジックでのsortBy
sortByは、コールバック関数を使ってより複雑なソートも可能です。

```php
$users = collect([
    ['name' => 'John', 'age' => 30, 'score' => 85],
    ['name' => 'Jane', 'age' => 25, 'score' => 90],
    ['name' => 'Doe', 'age' => 35, 'score' => 80],
    ['name' => 'Smith', 'age' => 30, 'score' => 95],
]);

$sortedUsers = $users->sortBy(function($user) {
    return [$user['age'], -$user['score']];
});

$sortedUsers->values()->all();

```

```
[
    ['name' => 'Jane', 'age' => 25, 'score' => 90],
    ['name' => 'Smith', 'age' => 30, 'score' => 95],
    ['name' => 'John', 'age' => 30, 'score' => 85],
    ['name' => 'Doe', 'age' => 35, 'score' => 80],
]
```
- コールバック関数内で複数の条件を指定することで、まずageで昇順に、その後scoreで降順にソートしています。
- -符号を付けることで、特定のキーに対して降順ソートを実現しています。

## orderByとは？
orderByは、LaravelのクエリビルダおよびEloquentで使用されるメソッドで、データベースレベルでソートします。大量のデータを扱う際に最も効率的であり、サーバーサイドでの負荷を軽減します。

### orderByの基本的な使い方
```php
Model::orderBy($column, $direction)->get();
```
- **$column:** ソート対象のカラム名
- **$direction:** ソート方向を指定する文字列。'asc'（昇順）または'desc'（降順）。デフォルトは'asc'。

### orderByを使った例
```php
$users = User::orderBy('age', 'asc')->get();

foreach ($users as $user) {
    echo $user->name . ' - ' . $user->age . "\n";
}
```

```
Jane - 25
John - 30
Doe - 35
```

- User::orderBy('age', 'asc')->get();で、usersテーブルのデータをageカラムに基づいて昇順にソートして取得しています。
- データベースクエリでソートを行うため、大量のデータでも高速に処理できます。

### 複数カラムでのソート
orderByメソッドはチェーンして複数のカラムでソートすることが可能です。

```php
$users = User::orderBy('age', 'asc')->orderBy('name', 'desc')->get();

foreach ($users as $user) {
    echo $user->name . ' - ' . $user->age . "\n";
}
```

```
Jane - 25
John - 30
Doe - 30
Smith - 35
```
- 最初にageで昇順にソートし、同じ年齢の場合はnameで降順にソートしています。
- この方法で、より細かい制御が可能になります。


## まとめ

| メソッド   | 使用場所                         | 主な用途                               | 特徴                                          |
|------------|----------------------------------|----------------------------------------|-----------------------------------------------|
| **usort**  | PHP配列全般                      | カスタムロジックによる配列のソート     | ユーザー定義関数を使用して柔軟なソートが可能。<br>元の配列を直接変更。 |
| **sortBy** | Laravelコレクション              | コレクションのソート                   | シンプルなソート機能。<br>元のコレクションを変更せず、新しいコレクションを返す。 |
| **orderBy**| Laravelクエリビルダ・Eloquent| データベースレベルでのデータソート     | データ取得時に効率的なソート。<br>大量データの処理に最適。 |

### 適切なメソッドを選択するポイント

- **パフォーマンス重視**: 大量のデータを扱う場合や、可能な限りデータベース側で処理を完結させたい場合は`orderBy`を使用。
- **コレクション操作**: 取得済みのデータをLaravelコレクションとして扱い、シンプルなソートを行いたい場合は`sortBy`を使用。
- **複雑なソートロジック**: 特殊な条件や複数の要素に基づいてソートを行いたい場合、特に配列データを扱う場合は`usort`を使用。