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

こんにちは、つかさです
今回はLaravelのクエリビルダについてまとめていこかなと思います。
どうゆうデータが欲しいかによって様々な書き方があるので混乱しがちですが、しっかり理解して整理していきましょう! :sunglasses:
さらに、実際にそのクエリビルダでどのようなSQLが走っているのかも理解できたらなと思っています。

## 基盤
初めにどのテーブルからデータを取得するのか指定する必要があります。
ここでは仮に`User`テーブルからデータを取得するとしましょう。
まず、`Illuminate\Support\Facades\DB`に`::table(テーブル名)`でusers テーブルのビルダインスタンスを取得します。クラスのインスタンスのような感じで捉えるとわかりやすいかもしれないです。
この時点ではまだデータを取得できていないのでご注意を!


```php:例
use Illuminate\Support\Facades\DB;

public function getUsers()
{
$users = DB::table('users');
}
```
`DB::table('users')`のsql
```sql:
select * from `users`
```

## データ取得
次に実際にテーブルの中身の取得していきます。
先ほど取得したusers テーブルのビルダインスタンスに対してメソッドを呼ぶことで取得することができます。
### getメソッド
- 結果データの全てを取得します
- Collectionとして返ってくる

|id|name|email|status|created_at|updated_at|
|:-:|:-:|:-:|:-:|:-:|:-:|
| 1 | John Doe | john@example.com | active | 2024-01-01 10:00:00 | 2024-01-02 12:00:00 |
| 2 | Jane Smith | jane@example.com  | active | 2024-01-03 14:00:00 | 2024-01-04 16:00:00 |
| 3 | Mike Brown | mike@example.com  |inactive| 2024-02-01 08:30:00 | 2024-02-02 09:45:00 |

```php:例
$users = DB::table('users')->get();

foreach ($users as $user) {
    echo "ID: {$user->id}, Name: {$user->name}, Email: {$user->email}, Status: {$user->status}\n";
}
```
```html:
ID: 1, Name: John Doe, Email: john@example.com, Status: active
ID: 2, Name: Jane Smith, Email: jane@example.com, Status: active
ID: 3, Name: Mike Brown, Email: mike@example.com, Status: inactive
```
実行されるSQL
```sql:
SELECT * FROM users;
```

:::note warn
 DB::table('users')と DB::table('users')->get()SQLの違いについて注意しよう。
 2つとも見た目は同じだが、2点異なる。
 ・1つ目はクエリが実行されているか？
 DB::table('users')は実行されておらず、DB::table('users')->get()はされている。
 ・2つ目は返り値。
　DB::table('users')はクエリビルダのインスタンスに対してDB::table('users')->get()はデータのコレクションになります。
:::

### firstメソッド
- 結果データの最初の 1 件のみを取得します
- stdClassのオブジェクトとして返ってくる
- もしデータがない場合は`null`が返ります

```php:例
$users = DB::table('users')->first();

echo "Name: {$user->name}, Email: {$user->email}\n";
```
```haml:
Name: John Doe, Email: john@example.com
```

実行されるSQL
```sql:
SELECT * FROM users LIMIT 1;
```

### soloメソッド
- 結果データが必ず 1 件であることを保証して取得します
- 「結果データが 0 件」「結果データが複数件」の場合は例外がスローされます
- １件だけならstdClassのオブジェクトとして返ってくる

```php:例
$user = DB::table('users')->where('email', 'john@example.com')->solo();
```
`john@example.com`を持つレコードは1件なので、stdClassのオブジェクトが取得できます。
別途`where`に関しては記載しますが、whereで取得条件を絞ることができます。
ここの例ではemailカラムに`john@example.com`を持つレコードという条件になります。
実行されるSQL
```sql:
SELECT * FROM users WHERE email = 'john@example.com' LIMIT 2;
```
#### ポイント
- LIMIT 2 を自動的に付けて 2件以上あるかをチェックしている

```php:データが2件以上ある場合
$user = DB::table('users')->where('status', 'active')->solo();
```

statusカラムに`active`をもつレコードは2件あるので、例外がスローされます。
` \Illuminate\Database\MultipleRecordsFoundException`

### valueメソッド
- 指定した 1 つのカラムのみを取得します
- もしデータがない場合は`null`が返ります

```php:例
$userName = DB::table('users')->value('name');
```

fristメソッドのカラムのみの取得バージョンみたいな感じです。

実行されるSQL
```sql:
SELECT `name` FROM `users` LIMIT 1
```

### pluckメソッド
- 指定カラム 1 つだけをコレクションで取得できます

```php:例
$userName = DB::table('users')->pluck('name');
```

```html:
Illuminate\Support\Collection Object
(
    [items:protected] => Array
        (
            [0] => John Doe
            [1] => Jane Smith
            [2] => Mike Brown
)
```

実行されるSQL
```sql:
SELECT `name` FROM `users`;
```
こっちはgetメソッドのカラムのみの取得バージョンみたいな感じになりますね。

:::note warn
getメソッド同様にCollectionで返ってくるが、getメソッドはCollectionの中にstdオブジェクトだが、plunkメソッドは連想配列なのでご注意を
:::
さらに、コレクションのキーをindexではなくカラムにすることができます。
やり方としては第2引数に対象のカラムを指定します。

```php:例
$userName = DB::table('users')->pluck('name','status');
```

```html:
Illuminate\Support\Collection Object
(
    [items:protected] => Array
        (
            [active] => John Doe
            [active] => Jane Smith
            [inactive] => Mike Brown
)
```

実行されるSQL
```sql:
SELECT `name`, `status` FROM `users`;
```

### existsメソッド
- 条件に対してレコードが存在するかを確認できます
- 存在すれば`true`、存在しなければ`false`が返ってきます

```php:例
$existsUsers = DB::table('users')->exists();
```

実行されるSQL
```sql:
SELECT EXISTS(SELECT * FROM `users`) AS `exists`;
```

### doesntExistメソッド
- existsメソッドの逆になります

```php:例
$existsUsers = DB::table('users')->doesntExist();
```

実行されるSQL
```sql:
SELECT NOT EXISTS(SELECT * FROM `users`) AS `not_exists`;
```

### toSqlメソッド
- SQL クエリを文字列として取得を取得することができます

データを取得するわけではないですが、どのようなクエリが実行されているのか確認できるので便利です。以下の例では` DB::table('users')`の部分のsqlを取得できます。

```php:例
$existsUsers = DB::table('users')->toSql();
```

```html:
select * from `users`
```

## まとめ
今回はクエリビルダの基盤部分とデータ取得するためのメソッドについて整理しました。普段はsqlを意識せずに取得できてしまいますが、内部でどのようなsqlが実行されているかまで理解することで、より視野が広がると思います。
クエリビルダは範囲が広いので複数の記事で分割して投稿していく予定です。
読んでいただきありがとうございました！