開発ブログ

株式会社Nextatのスタッフがお送りする技術コラムメインのブログ。

電話でのお問合わせ 075-744-6842 ([月]-[金] 10:00〜17:00)

  1. top >
  2. 開発ブログ >
  3. PHP >
  4. Laravel >
  5. 【Laravel】Collectionにsoleメソッドが追加されたので使ってみた

【Laravel】Collectionにsoleメソッドが追加されたので使ってみた

こんにちは。
ニシザワです。


Laravel9が迫ってますね
Laravel8のマイナーバージョンアップでも知らないうちにいろいろな機能が追加されていたりします。
今回はそのうちの一つを紹介

soleとは

soleは唯一の、たった一つのという意味があり
Collectionでのsoleは条件に当てはまるものが1つだけの場合値を返してくれるメソッドです。
BuilderクラスのsoleはLaravel8で実装されています。(参考)

soleメソッドの内容

    /**
     * Get the first item in the collection, but only if exactly one item exists. Otherwise, throw an exception.
     *
     * @param  (callable(TValue, TKey): bool)|string  $key
     * @param  mixed  $operator
     * @param  mixed  $value
     * @return TValue
     *
     * @throws \Illuminate\Support\ItemNotFoundException
     * @throws \Illuminate\Support\MultipleItemsFoundException
     */
    public function sole($key = null, $operator = null, $value = null);
soleメソッドのinterfaceを見ていきましょう。
第一引数はcallableの指定が可能となっています。
keyがvalueと等しいもの等を検索し、一つだけの場合結果を返してくれます。
それ以外の場合は
結果がない場合は\Illuminate\Support\ItemNotFoundExceptionを投げます。
結果が複数の場合は\Illuminate\Support\MultipleItemsFoundExceptionを投げます。

使い方

予めusersテーブルに値を用意しておきます。

+----+--------+--------------------+
| id | name   | email              |
+----+--------+--------------------+
|  1 | test   | test@example.com   |
|  2 | hoge   | hoge@example.com   |
|  3 | fuga   | fufa@example.com   |
|  4 | nextat | nextat@example.com |
|  5 | nextat | nextat2@example.com |
+----+--------+--------------------+
UserModelをCollectionに詰めておきます

$users = App\Models\User::all();

条件に当てはまるアイテムが1つの場合


$users->sole('email', 'nextat@example.com');
// または
$users->sole(function(App\Models\User $user): bool {
        return $user->email === 'nextat@example.com'
    });

//  App\Models\User {
//     id: 4,
//     name: "nextat",
//     email: "nextat@example.com",
//   }
//
第2引数のオペレーターは省略可能です。

条件に当てはまるアイテムが2つ以上の場合


$users->sole('name', 'nextat');
// または
$users->sole(function(App\Models\User $user): bool {
        return $user->name === 'nextat'
    });

// \Illuminate\Support\MultipleItemsFoundException

条件に当てはまるアイテムがない場合


$users->sole('name', 'nextat2');
// または
$users->sole(function(App\Models\User $user): bool {
        return $user->name === 'nextat2'
    });

// \Illuminate\Support\ItemNotFoundException
今まで、唯一の要素を取得していた時は以下の様に場合分けしていたのではないでしょうか

$filteredUsers = $users->filter(
    function(App\Models\User $user): bool {
        return $user->name === 'nextat2'
    });

if ($filteredUsers->count() > 1) {
    throw new Illuminate\Support\MultipleItemsFoundException();
}

$user = $filteredUsers->first();

if ($user === null) {
    throw new Illuminate\Support\ModelNotFoundException();
}
soleを使うと例外を投げてくれるので便利ですね。 参考にしてみてください。
TOPに戻る