【Laravel】知っていると便利なヘルパー関数!tap()の使い方を紹介します

Laravel

前回firstOrCreate()について説明した際に、tap()について言及しました。

【Laravel】EloquetモデルでfirstOrCreate()等のデータを取得 or 登録するメソッドについてのまとめ
概要EloquentにはfirstOrCreate()のように、データの取得と登録を同時に行うメソッドが存在しています。そうしたメソッドを使用すると、データの存在チェックのためのif文を減らしたり、変数をnullで初期化して宣言する...

tapIlluminate\Support\helpers.phpで定義されているヘルパー関数で、Laravelの生みの親のTaylor Otwell氏がtap()について解説しているように、簡潔なコードを書くのに役立つ便利な関数です。

https://medium.com/@taylorotwell/tap-tap-tap-1fc6fc1f93a6

今回はそんなtap関数の動作や、使い方について紹介したいと思います。

※使用したLaravelのバージョンは5.6です。

スポンサーリンク

解説

tap()の使用例

まず最初にtap()の使用例を示します。


$model = tap(Post::findOrFail(1), function ($post) {
    $post->title = 'How to use tap function';
});

上記の例は、findOrFail()を使用してDBを検索、Postモデルのインスタンスを取得し、そのtitleを書き換えています。

tap()は第2引数にクロージャを受け取り、そのクロージャーの引数には、tap()の第1引数が渡されます。

つまり、$postには、Post::findOrFail()の結果がセットされます。

そして、クロージャー内の処理を実行した後、$postが返却されるのです。

クロージャーに引数で渡した値以外をreturn出来ない点に注意下さい。

このサンプルでのtap()のメリットは、下記の2点が挙げられます。

  • findOrFail()の結果を、一時変数を作成して格納しなくて良い
  • クロージャーのスコープ内で処理が完結している

tap()の内部で実行した結果は、$modelに代入する以外に影響を及ぼさないようになっています。

また、tap()の戻り値はtap()の第1引数に設定した変数となるため、この例ではPostモデルのインスタンスが返却されます。

そのため、下記のように、メソッドチェーンで更に別の処理を実行することが可能です。


$array = tap(Post::findOrFail(1), function ($post) {
    $post->title = 'Title changed';
})->toArray();

tap()を使ってfindOrCreate()を実装してみる

Illuminate\Database\Eloquent\Builderクラスでは、既にfirstOrCreate()が実装されていますので、tap()を使って、find()とcreate()を行うfindOrCreate()を新たに追加してみたいと思います。

Builderクラスに機能を追加するために、Laravelのマクロ機能を利用します。

マクロについては別の記事で紹介していますので、詳細はそちらを参照下さい。

【Laravel】Macroを使ってCollectionクラスやファサードにメソッドを追加する
LaravelのCollectionクラスやファサードにメソッドを追加する方法を紹介しています!

マクロを登録するためのサービスプロバイダーを作成したら、下記のようにサービスプロバイダーを実装します。


find($id))) {
                return $instance;
            }

            return tap($this->newModelInstance($attributes), function ($instance) use ($id) {
                $instance->save();
            });
        });
    }

    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

そして、config/app.phpにサービスプロバイダーを登録します。


    'providers' => [
        (中略)
        App\Providers\MacroServiceProvider::class,

    ],

以上で実装は完了です。

追加したfindOrCreate()は下記のように使用します。


$post = Post::findOrCreate(1, [
    'title'     => 'findOrCreate()を追加',
    'user_id'   => 1,
    'content'   => 'Content about tap helper function...',
    'is_public' => true,
]);

おわりに

今回はtap()の使い方と、tap()を使ったメソッドの実装例を紹介しました。

tap()はスコープ内に処理を閉じ込めたり、メソッドチェーンを組み込んだりと、今回紹介した以外にも様々なシーンで活用できる可能性があるメソッドなので、他にも効果的な使い方を探したいと思います。