Laravelで「お友達紹介」機能をつくる

こんにちは。フリーランス・コンサルタント&エンジニアの 九保すこひ です。

さてさて、この間「インターネットの広告費がテレビを抜いた❗」というニュースがありました。

つい10年前では考えられないことが現実になり、「うーん、インターネットも歴史を持ちはじめたんだな😲」としみじみしてしまいました。

そしてそんなとき、とある機能を思い出しました。

それは・・・

「お友達紹介」機能

です。

というのも、ある時期に「お小遣いサイト」と呼ばれる「コマーシャルを見たり、資料請求するとポイントを受け取ることができ、さらに換金もできる」というウェブサイトが多くリリースされたことを思い出したからです。

そして、このサイトでは紹介されたURLから誰かがユーザー登録すると、ご褒美としてポイントがもらえたりします。

つまり、流れとして次のようになります。

  1. 太郎さんが、次郎さんに登録URLを教えてあげる
  2. 次郎さんが登録する
  3. ご褒美として太郎さんにポイントを付与する(サイトによっては次郎さんもポイントをゲットできる)

そこで❗

今回はLaravelを使ってこの「お友達紹介」機能を実装してみたいと思います。

ぜひ皆さんの参考になれば嬉しいです😊✨
(最後にソースコード一式をダウンロードできます)

「梅雨に入ったので、クセッ毛が
打ち上げられたワカメ化してます😫」

開発環境: Larave 7.x

前提として

今回もLaravelにログイン機能がインストールされている必要があります。そのため、まだの方は以下のページを参考にして先にインストールをし、テストユーザーを用意しておいてください。

Laravel6.x以降でログイン機能をインストールする方法

やりたいこと

流れは冒頭で紹介したとおりですが、実際に紹介で登録があったら特典として、以下2つを実行するようにしてみます。

  • 紹介「した」ユーザーには 500 ポイントを付与
  • 紹介「された」ユーザーには 300 ポイントを付与

さらに、「誰の紹介で登録したか」というデータも保存します。(あとで「過去に何人のユーザーを紹介したか」も分かるようになります)

では実際にコードを書いていきましょう❗

DBの準備をする

もちろん初期状態では、「ポイント」や「紹介者データ」は保存されませんのでDBテーブルに追加していきます。

usersテーブルにポイントのフィールドを追加する

まずはポイントを保持するフィールドです。
usersテーブルのマイグレーションを以下のように変更してください。

/database/migrations/****_**_**_******_create_users_table.php

// 省略

public function up()
{
    Schema::create('users', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->string('email')->unique();
        $table->timestamp('email_verified_at')->nullable();
        $table->string('password');
        $table->integer('points')->default(0)->comment('ポイント'); // 👈 追加
        $table->rememberToken();
        $table->timestamps();
    });
}

// 省略

紹介者データを保存するモデル&DBテーブルをつくる

続いて、「誰が誰を紹介したか」を管理するuser_introductionsテーブルをつくっていきます。

以下のコマンドを実行してください。

php artisan make:model UserIntroduction -m

するとモデルとマイグレーションが一気にが作成されるので、マイグレーションの中身を以下のように変更します。

/database/migrations/****_**_**_******_create_user_introductions_table.php

// 省略

public function up()
{
    Schema::create('user_introductions', function (Blueprint $table) {
        $table->id();
        $table->unsignedBigInteger('introduced_user_id')->comment('紹介をしたユーザーのID');
        $table->unsignedBigInteger('registered_user_id')->comment('紹介経由で登録したユーザーのID');
        $table->timestamps();

        $table->foreign('introduced_user_id')->references('id')->on('users');
        $table->foreign('registered_user_id')->references('id')->on('users');
        $table->unique(['introduced_user_id', 'registered_user_id']);
    });
}

// 省略

マイグレーションを実行する

では、ここまでで追加・変更したマイグレーションでDBを再構築しましょう。

php artisan migrate:fresh --seed

実行が完了すると、テーブルは以下のようになります。

Userモデルから紹介用のURLが取得できるようにする

次にUserモデルにAccessorを追加して以下のように「友達の紹介用URL」が取得できるようにしましょう。

echo $user->introduction_url; // 👈 紹介用URLが取得できる

※ なお、Accessorとは、DBテーブルには存在していないデータを独自に追加する機能のことです。詳しくは、全15件!Laravel・使い回しできるAccessor実例 をご覧ください。

<?php

// 省略

class User extends Authenticatable
{
    // 省略

    // Accessor
    public function getIntroductionUrlAttribute() {

        $user_id = $this->id;

        return route('register', [
            'introduced_user_id' => $user_id
        ]);

    }

}

これで、$user->introduction_urlから以下のようなURLが取得できるようになりました。

http://***/register?introduced_user_id=(紹介者のユーザーID)

友達経由で登録したら実行されるイベントをつくる

続いて、友達の紹介でユーザー登録されたときに実行されるイベント「UserIntroduced」を先につくっておきます。

以下のコマンドを実行してください。

php artisan make:event UserIntroduced

実行するとファイルが作成されるので、中身を以下のようにしましょう。

/app/Events/UserIntroduced.php

// 省略

public function __construct(User $introduced_user, User $registered_user)
{
    // 友達紹介「した」ユーザーの処理
    $introduced_user->points = $introduced_user->point + 500; // 500ポイントを付与
    $introduced_user->save();

    // 友達紹介「された」ユーザーの処理
    $registered_user->points = $registered_user->point + 300; // 300ポイントを付与
    $registered_user->save();

    // 紹介情報を保存
    $user_introduction = new \App\UserIntroduction();
    $user_introduction->introduced_user_id = $introduced_user->id;
    $user_introduction->registered_user_id = $registered_user->id;
    $user_introduction->save();
}

// 省略

中身としては、

  • 友達紹介「した」ユーザーには500ポイントを追加
  • 友達紹介「された」ユーザーには300ポイントを追加

そして、最後に「誰が誰を紹介したか」のデータを保存しているだけです。

ユーザー登録ページを友達紹介に対応させる

では準備は整いましたので、Laravelのユーザー登録に友達紹介機能を追加していきます。

登録フォームをカスタマイズする

まずは登録フォームのテンプレートを以下のように変更してください。

<!-- 省略 -->

<div class="card-body">
    <form method="POST" action="{{ route('register') }}">
        @csrf
            
        <!-- 👇追加:ここはブラウザには表示されませんが、データは送信されます -->
        <input type="hidden" name="introduced_user_id" value="{{ request('introduced_user_id', '') }}">

<!-- 省略 -->

内容としては、(紹介の場合に)パラメータとして取得できるintroduced_user_id<input type="hidden">で再送信できるようにしているだけです。

登録後にUserIntroducedイベントが実行されるようにする

そして、友達紹介でユーザー登録されたらイベントを実行する部分です。

RegisterController.phpの中にregistered()というメソッドを追加(実際にはすでに用意されているので上書き)して中身を以下のようにしてください。

/app/Http/Controllers/Auth/RegisterController.php

<?php

// 省略

class RegisterController extends Controller
{
    // 省略

    protected function registered(Request $request, $registered_user) // ユーザー登録されたら実行される
    {
        $introduced_user = \App\User::find($request->introduced_user_id);

        if(!is_null($introduced_user)) { // 紹介経由でユーザー登録された場合

            event(new UserIntroduced($introduced_user, $registered_user));

        }
    }
}

テストしてみる

では、実際にテストしてみます❗

太郎さん(ID: 1)が送ったURLから花子さんがユーザー登録する」というストーリーで実行してみましょう。

アクセスするURLは、http://***/register?introduced_user_id=1です。(1は、太郎さんのIDです)

フォームに登録情報を入力して送信すると・・・・・・

はい❗
ユーザー登録が完了しました。

では、DBテーブルを確認してみましょう。
まずはポイントの付与です。

うまく太郎さんにも花子さんにもポイントが追加されています。
では紹介情報の方はどうでしょうか。

はい❗
上手く太郎さん(ID: 1)と花子さん(ID: 4)のデータが保存されています。

成功です😊✨

おまけ: リレーションシップでデータ取得

せっかくお友達紹介機能をつくったので、その後の使い方として想定される「過去にどのユーザーを紹介してきたか」というデータをリレーションシップで一気に取得してみましょう。

ではまず、user_introductionsテーブルにテストデータをつくります。
内容は、以下の2つです。

  • 次郎さんは、太郎さんの紹介で登録した
  • 三郎さんも、太郎さんの紹介で登録した

※ つまり、「太郎さん」は「次郎さん」と「三郎さん」の2人に登録してもらったことになります。

実際のテーブルはこうなります。

では、次にUserモデルにuser_introductions()を追加してください。

/app/User.php

<?php

// 省略

class User extends Authenticatable
{
    // 省略
    public function user_introductions() {

        return $this->hasManyThrough(
            'App\User',
            'App\UserIntroduction',
            'introduced_user_id',
            'id',
            'id',
            'registered_user_id'
        )->orderBy('id', 'asc');

    }

}

そして、with()でリレーションシップを呼び出しながらデータ取得すると・・・・・・

Route::get('user_introduction', function(){

    $users = \App\User::with('user_introductions')->get();
    dd($users->toArray());

});

以下のように太郎さんのuser_intoroductionsには、次郎さんと三郎さんのデータが入ってくることになります。

成功です😊✨

ちなみに、このリレーションシップは以下のように「行って帰ってくる」構造になっています。

また、以下のようにすると各ユーザーの紹介人数を取得することもできます。

$users = \App\User::with('user_introductions')->get();

foreach ($users as $user) {

    dump($user->name .'さん の紹介で登録したユーザー数: '. $user->user_introductions->count());

}

実際にブラウザで実行したものがこちらです。

ダウンロードする

今回実際に開発したソースコード一式を以下からダウンロードできます。

※ ただし、マイグレーションなどはご自身で行ってください。

Laravelで「お友達紹介」機能をつくる
開発のご依頼お待ちしております
開発のご依頼はこちらから: お問い合わせ
どうぞよろしくお願いいたします! by 九保すこひ

おわりに

ということで、今回はLaravelを使って「お友達紹介」機能をつくってみました。

今回の記事では、紹介時にポイントの付与をしていますが、アイデア次第でいろいろな「特典」を紹介者、登録者につけてあげることができると思います。

また、過去の開発ではいろいろと複雑なコードを書く必要がありましたが、Laravelではすでに用意されている機能がフレキシブルに対応してくれるので、特別難しいコードを書かずに実装ができます。(さすがLaravelです👍)

ぜひ皆さんのサイトでもやってみてくださいね。

ではでは〜❗

「ポイントサイトのアカウント、
まだ残ってるのかな❓」

このエントリーをはてなブックマークに追加       follow us in feedly