新しく追加されたクエリビルダーのsoleメソッドとは


はじめに

Laravelのバージョンが8.23以上からクエリビルダーにsoleメソッドが導入されています。
soleメソッドは単一レコードに一致する場合のみ、一致したレコードを取得します。一致しない場合は例外エラーが発生します。
この記事は簡単なデモを通じて下記内容について解説しています。

  • soleメソッドの使い方について
  • データ取得メソッドのfirst、get、soleの違いについて

事前準備

予めuserテーブルに次の値をセットしています。

+----+-------+--------------------+-------------------+--------------------------------------------------------------+----------------+---------------------+---------------------+
| id | name  | email              | email_verified_at | password                                                     | remember_token | created_at          | updated_at          |
+----+-------+--------------------+-------------------+--------------------------------------------------------------+----------------+---------------------+---------------------+
|  1 | test1 | [email protected]  | NULL              | $2y$10$9U3mn6osC2Xek9j1BvPV1OMoG2zVtNOG.Cikgg62UO/O2glF7q2Ky | NULL           | 2021-02-13 07:56:52 | 2021-02-13 07:56:52 |
|  2 | test2 | [email protected]  | NULL              | $2y$10$.TYqe0M6q3feUwqSdrUFAO9XIG4ja4tQC6IDLkEy1DI23EXFPX7I6 | NULL           | 2021-02-13 07:57:15 | 2021-02-13 07:57:15 |
|  3 | test3 | [email protected]  | NULL              | $2y$10$E7SPrfMjwyLFlP.7YB0Ak.DjO73IOdhjEQ375eEaEbcv140zPt63C | NULL           | 2021-02-13 07:57:47 | 2021-02-13 07:57:47 |
|  4 | test3 | [email protected] | NULL              | $2y$10$DrKwopQ2ClXxLozoKD/yque2A20Hl4Bu.JRcb9nTvJTL0CEnOT8.O | NULL           | 2021-02-14 09:38:26 | 2021-02-14 09:38:26 |
+----+-------+--------------------+-------------------+--------------------------------------------------------------+----------------+---------------------+---------------------+
4 rows in set (0.01 sec)

今回はtinkerを使用してsoleメソッドの挙動について確認していきたいと思います。
ちなみにtinkerの立ち上げは下記コマンドになります。

$ php artisan tinker

soleメソッドの使い方

soleメソッドを使用するときのケースとして下記の3つが想定されます。

  1. クエリに一致するレコードが単一の場合
  2. クエリに一致するレコードがゼロの場合
  3. クエリに一致するレコードが複数の場合

クエリに一致するレコードが単一の場合

getメソッドの場合

>>> $user = User::where('name', 'test1')->get();
=> Illuminate\Database\Eloquent\Collection {#3406
     all: [
       App\Models\User {#3410
         id: 1,
         name: "test1",
         email: "[email protected]",
         email_verified_at: null,
         created_at: "2021-02-13 07:56:52",
         updated_at: "2021-02-13 07:56:52",
       },
     ],
   }

firstメソッドの場合

>>> $user = User::where('name', 'test1')->first();
=> App\Models\User {#3399
     id: 1,
     name: "test1",
     email: "[email protected]",
     email_verified_at: null,
     created_at: "2021-02-13 07:56:52",
     updated_at: "2021-02-13 07:56:52",
   }

soleメソッドの場合

>>> $user = User::where('name', 'test1')->sole();
=> App\Models\User {#3410
     id: 1,
     name: "test1",
     email: "[email protected]",
     email_verified_at: null,
     created_at: "2021-02-13 07:56:52",
     updated_at: "2021-02-13 07:56:52",
   }

クエリに一致するレコードがゼロの場合

getメソッドの場合

>>> $user = User::where('name', 'test1234')->get();
=> Illuminate\Database\Eloquent\Collection {#3408
     all: [],
   }

firstメソッドの場合

>>> $user = User::where('name', 'test1234')->first();
=> null

soleメソッドの場合

>>> $user = User::where('name', 'test1234')->sole();
Illuminate\Database\Eloquent\ModelNotFoundException with message 'No query results for model [App\Models\User].'

クエリに一致するレコードが複数の場合

getメソッドの場合

>>> $user = User::where('name', 'test3')->get();
=> Illuminate\Database\Eloquent\Collection {#4299
     all: [
       App\Models\User {#3399
         id: 3,
         name: "test3",
         email: "[email protected]",
         email_verified_at: null,
         created_at: "2021-02-13 07:57:47",
         updated_at: "2021-02-13 07:57:47",
       },
       App\Models\User {#3403
         id: 4,
         name: "test3",
         email: "[email protected]",
         email_verified_at: null,
         created_at: "2021-02-14 09:38:26",
         updated_at: "2021-02-14 09:38:26",
       },
     ],
   }

firstメソッドの場合

>>> $user = User::where('name', 'test3')->first();
=> App\Models\User {#3404
     id: 3,
     name: "test3",
     email: "[email protected]",
     email_verified_at: null,
     created_at: "2021-02-13 07:57:47",
     updated_at: "2021-02-13 07:57:47",
   }

soleメソッドの場合

>>> $user = User::where('name', 'test3')->sole();
Illuminate\Database\MultipleRecordsFoundException

まとめ

デモを通してsoleメソッドの使用ケースは
単一のレコードの取得が必要で、かつ必ず単一レコードのみが存在することを保証されているときだと思いました。

参考

Understanding the sole() Query Builder Method