〜エンジニア初学者の開発日記〜 九の巻

こんにちは、つかさです
今回は取得するデータに対して加工するメソッドについてまとめたいと思います。
一緒に理解できるよう頑張っていきましょう！:grin:

## 前提条件

### Usersテーブル
|id|name|email|status|age|created_at|updated_at|
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| 1 | John Doe | john@example.com | active | 22 | 2024-01-01 10:00:00 | 2024-01-02 12:00:00 |
| 2 | Jane Smith | jane@example.com  | active | 30 | 2024-01-03 14:00:00 | 2024-01-04 16:00:00 |
| 3 | Mike Brown | mike@example.com  |inactive| 55 | 2024-02-01 08:30:00 | 2024-02-02 09:45:00 |
| 4 | SUZUKI Taro | trao@example.com  |inactive| 40 | 2024-02-10 09:30:00 | 2024-03-02 12:40:00 |


## 結果データのソート

### orderByメソッド
- 取得するデータの並び順を指定します

```php:例
$userBuilder->orderBy('id')
```
```sql:例
Select * from `users` order by `id` asc
```

```php:例
$userBuilder->orderBy('id'. 'desc')
```
```sql:例
Select * from `users` order by `id` desc
```
デフォルトで昇順になります。第二引数に昇順(asc), もしくは降順(desc) のどちらかを指定することも出来ます。

```php:例
$userBuilder->orderBy('age')
             ->orderBy('id')
```
```sql:例
 Select * from `users` order by `age` asc, `id` asc
```
1. まず age を**昇順（デフォルト）**でソート
2. age が同じ値のレコードが複数ある場合、その中で id を昇順でソート

### orderByDescメソッド
第二引数に`desc`と指定しなくても降順にすることができる
```php:例
$userBuilder->orderByDesc('id')
```
```sql:例
Select * from `users` order by `id` desc
```

### latestメソッド
- デフォルトで`created_at` カラムが降順にソートされます

```php:例
$userBuilder->latest()
```
```sql:例
Select * from `users` order by `created_at` desc
```
引数を渡すことでカラムを指定することも可能です
```php:例
$userBuilder->latest('id')
```
```sql:例
Select * from `users` order by `id` desc
```

### oldestメソッド
- デフォルトで`created_at` カラムが昇順にソートされます

```php:例
$userBuilder->oldest()
```
```sql:例
Select * from `users` order by `created_at` asc
```
引数を渡すことでカラムを指定することも可能です
```php:例
$userBuilder->oldest('id')
```
```sql:例
Select * from `users` order by `id` asc
```

### inRandomOrderメソッド
- 結果データをランダムな順番にソートされます
```php:例
$userBuilder->inRandomOrder()
```
```sql:例
Select * from `users` order by RAND()
```

### reorderメソッド
- 既にセットしたソート順を削除することができます
```php:例
// 共通のクエリ条件
$query = User::where('status', 'active')->orderBy('created_at', 'desc');

// ある場合は、created_at降順のまま使う
$usersDefault = $query->get();

// 別のケースでは、orderを上書きして name 昇順にしたい
$usersByName = $query->reorder('name', 'asc')->get();
```
reorderメソッドを使用することwhere条件を残しつつ、ソートを変更することが可能です。
　つまりは$usersByNameには以下のクエリで取得したデータが入ります
```sql:例
Select * from users where status = 'active' order by name ASC
```

削除してデフォルトにするだけではなく、違う条件のソートに編集することも可能です

```php:例
$query = User::where('status', 'active')->orderBy('created_at', 'desc');

$usersByName = $query->reorder('email', 'desc')->get();
```
```sql:$usersByNameの結果
Select * from `users` order by `email` desc
```

## 結果データのグループ化と絞り込み
- 以前の投稿で既に出てきていますが、groupByでグループ化し、グループ化したものに対しての絞り込みにはhavingを使用します

```php:例
$results = DB::table('orders')
    ->select('user_id', DB::raw('COUNT(*) as order_count'))
    ->groupBy('user_id')
    ->having('order_count', '>=', 2)
    ->get();
```
ユーザー（user_id）ごとの注文数を集計し、注文数が 2回以上 のユーザーだけを取得しています
```sql:例
SELECT user_id, COUNT(*) AS order_count
FROM orders
GROUP BY user_id
HAVING COUNT(*) >= 2;
```

## 取得レコード数の制限・スキップ

### limitメソッド
- 取得するレコード数を制限できます

```php:例
$userBuilder->limit(3)
```
```sql:例
select * from `users` limit 3
```

### offsetメソッド
- 結果レコードの何件目から取得するかを指定することができます

```php:例
$userBuilder->offset(2)
            ->limit(3)
```
```sql:例
select * from `users` limit 3 offset 2
```

:::note info
ちなみにlimit()→take()、offset()→skip()にそれぞれ置き換えることができます
:::

## 判定式にる検索条件

### whenメソッド
- 条件が真（true）であるときのみクエリに特定の処理を追加するための便利なメソッドです

```php:基本構文
$query->when($condition, function ($query, $value) {
    return $query->where('column', $value);
});
```
1\. $condition：真偽値または値（null 以外など）

2\. value： $condition の値（第2引数のクロージャに渡される）

3\. 条件が false や null の場合、クロージャの中身は実行されません。

```php:例: 検索条件がある場合だけ絞り込み
$keyword = request('keyword');

$users = DB::table('users')
    ->when($keyword, function ($query, $keyword) {
        return $query->where('name', 'like', "%{$keyword}%");
    })
    ->get();
```
keyword が空なら where 条件はつかなず、keyword が "John" なら WHERE name LIKE '%John%' が追加さます

```sql:$keyword に "John" が入っていた場合
SELECT * FROM users
WHERE name LIKE '%John%';
```
```sql:$keyword が null または空文字列の場合
SELECT * FROM users;
```

### まとめ

読んでいただきありがとうございました！
しばらく期間が空いてしまいましたが、これからも自分のペースで記事を更新したり、新たな記事を書いていこうと思うので是非見ていただけたらなと思います！:grin: