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

Laravel

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

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

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

Tap, Tap, Tap – Taylor Otwell – Medium
One of my favorite helpers methods in Laravel is tap. On first glance, this Ruby inspired function is pretty odd. Here is the basic…

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