［Laravel］Twitterクローンアプリの、フォロー機能のコード手順メモ。

現在、教材を見ながらTwitterのクローンアプリを作っています。フォロー機能のコード手順メモです。

手順１：　まず、以下がフォローリストのViewコード。アバター部分はまだハードコーディング。

```friends-list.blade.php
<h3 class="font-bold text-lg mb-4">フォローリスト</h3>

<ul>
  @foreach (auth()->user()->follows as $user)
  <li class="mb-4">
    <div class="flex items-center text-sm">
      <img src="/images/avator.png" alt="" class="rounded-full mr-2 w-10">
      {{ $user->name }}
    </div>
  </li>
  @endforeach
</ul>
```

手順２：　 `@foreach (auth()->user()->follows as $user)` の部分で使っている、followsのリレーションを設定します。
ユーザーは沢山の他のユーザーをフォローすることができるから、リレーションはbelongsToMany()にします。このリレーションで、どのユーザーがどのユーザをフォローしているのかを管理できます。

```app\Models\User.php
    public function follows() {
        return $this->belongsToMany(User::class);
    }
```


手順３：　pivotテーブルとなるfollowsテーブルを作成します。

```
php artisan make:migration create_follows_table
```

手順４：　マイグレーションファイルを設定します。
ユーザー間及びフォローしているユーザー間の関係を設定する為には、'user_id' と、'following_user_id' が必要になります。
` $table->primary(['user_id', 'following_user_id']);` の部分で二つプライマリーキーを指定しているのは、ユーザーがボタンを二度押しとかした時に重複を許さないようにする為。

```database\migrations\2020_09_30_135049_create_follows_table.php
    public function up()
    {
        Schema::create('follows', function (Blueprint $table) {
            $table->primary(['user_id', 'following_user_id']);
            $table->foreignId('user_id');
            $table->foreignId('following_user_id');
            $table->timestamps();

            $table->foreign('user_id')
            ->references('id')
            ->on('users')
            ->onDelete('cascade');

            $table->foreign('following_user_id')
            ->references('id')
            ->on('users')
            ->onDelete('cascade');
        });
    }
```

手順５： マイグレーションします。

```
php artisan migrate
```

手順６：　取り敢えず、followsテーブルに手動でデータを入れてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235741/fdc5f8ae-99b7-66ac-b4c0-eb9c6ba36641.png)

因みに、既に作ってあるusersテーブルはこのような感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235741/2cbeb7e2-e3b1-f87e-022b-332809275981.png)


手順７：　これからtinkerで確認作業をしていくのですが、その前にUserモデルを以下のように修正しておきます。
'follows'とするのは、Laravelでは慣習的にpivotテーブルの名前は、双方のテーブル名をアルファベット順にアンダーバーでつなげる為です。今回の場合だと『user_user』というファイル名をLaravelが認識するのですが、そうではなくてfollowsだよ、と伝える為です。また、カスタムしたカラムネームを使っている為、foreignPivotKeyとrelatedPivotKeyを明示します。（PivotテーブルでLaravelが認識するデフォルトのカラムネームは、『モデル名\_id』です。これと異なる場合は、明示する必要があります。今回の場合だと、foreignPivotKeyとrelatedPivotKeyの両方ともuser_id。）

```app\Models\User.php
    public function follows() {
        return $this->belongsToMany(User::class, 'follows', 'user_id', 'following_user_id');
    }
```

手順８：　tinkerを立ち上げて確認してみます。

```
php artisan tinker
```

```
App\Models\User::find(1)->follows;
```

Userモデルのインスタンスが返されて、以下のように表示されます。Userモデルのid1のユーザーがフォローしている、id3と5のユーザーが出てきます。

```
>>> App\Models\User::find(1)->follows;
=> Illuminate\Database\Eloquent\Collection {#3772
     all: [
       App\Models\User {#4389
         id: 3,
         name: "原田 里佳",
         email: "sugiyama.taichi@example.com",
         email_verified_at: "2020-10-06 12:13:24",
         current_team_id: null,
         profile_photo_path: null,
         created_at: "2020-10-06 12:13:24",
         updated_at: "2020-10-06 12:13:24",
         pivot: Illuminate\Database\Eloquent\Relations\Pivot {#4177
           user_id: 1,
           following_user_id: 3,
         },
       },
       App\Models\User {#4140
         id: 5,
         name: "宮沢 充",
         email: "ryohei11@example.com",
         email_verified_at: "2020-10-06 12:13:24",
         current_team_id: null,
         profile_photo_path: null,
         created_at: "2020-10-06 12:13:24",
         updated_at: "2020-10-06 12:13:24",
         pivot: Illuminate\Database\Eloquent\Relations\Pivot {#4333
           user_id: 1,
           following_user_id: 5,
         },
       },
     ],
   }
```

id3のユーザを検索して見てみると。。。

```
App\Models\User::find(3)->follows;
```

何も出てこないのでOKです。

```
=> Illuminate\Database\Eloquent\Collection {#4394
     all: [],
```

手順９：　リレーション設定したものを、データベースに保存する関数を作ります。

```app\Models\User.php
    public function follow(User $user) {    // ←この関数追記
        return $this->follows()->save($user);
    }

    public function follows() {
        return $this->belongsToMany(User::class, 'follows', 'user_id', 'following_user_id');
    }
```

手順１０：　上記で作ったfollow()関数を、tinkerで確認していくのですが、その前にデータをリフレッシュしておきます。

```
php artisan migrate:fresh
```

手順１１：　新たにuserテーブルにデータを入れていきます。このような感じ。（id1だけはブラウザのregisterページから手動で登録して、その他はFactory機能で登録しました。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235741/f69ce349-c60d-1f04-d818-10d5f17349ea.png)

手順１２：　tinkerでフォローの設定・確認をしていきます。
id1(ログインしている自分のid)が、id3とid5をフォローしていて、id3とid5がそれぞれid1をフォローしている、という設定をしてみます。（相互フォロー）

follow()関数に渡すのは、ユーザーモデルのインスタンスでなければいけないので、それぞれのidを探して、変数に格納します。

```
$me = App\Models\User::find(1);
```

```
$taichi = App\Models\User::find(3);
```

```
$yoko = App\Models\User::find(5);
```

手順１３：　follow()関数を使って、それぞれがフォローするようにテーブルに登録します。

```
$me->follow($taichi);
$me->follow($yoko);
$taichi->follow($me);  
$yoko->follow($me);  
```

テーブルには以下のように入ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235741/6e0d00f2-1a27-6dfb-72ed-9360bd5d6081.png)
ブラウザで確認(id1のアカウント)すると、ちゃんと表示もされています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235741/271300aa-dff2-0336-7f95-ef98633072b0.png)

手順１４：　id1がid6をフォローしてみます。

```
$yumiko = App\Models\User::find(6);
```

```
$me->follow($yumiko);
```

手順１５：　id1がフォローしている全idを確認してみると、以下のように出ます。

```
$me->follows;
```

```
=> Illuminate\Database\Eloquent\Collection {#4390
     all: [
       App\Models\User {#4391
         id: 3,
         name: "若松 太一",
         email: "manabu.saito@example.com",
         email_verified_at: "2020-10-06 17:02:31",
         current_team_id: null,
         profile_photo_path: null,
         created_at: "2020-10-06 17:02:31",
         updated_at: "2020-10-06 17:02:31",
         pivot: Illuminate\Database\Eloquent\Relations\Pivot {#4394
           user_id: 1,
           following_user_id: 3,
         },
       },
       App\Models\User {#4392
         id: 5,
         name: "喜嶋 陽子",
         email: "minoru89@example.org",
         email_verified_at: "2020-10-06 17:02:31",
         current_team_id: null,
         profile_photo_path: null,
         created_at: "2020-10-06 17:02:31",
         updated_at: "2020-10-06 17:02:31",
         pivot: Illuminate\Database\Eloquent\Relations\Pivot {#4333
           user_id: 1,
           following_user_id: 5,
         },
       },
       App\Models\User {#4395
         id: 6,
         name: "中津川 裕美子",
         email: "lkimura@example.com",
         email_verified_at: "2020-10-06 17:02:31",
         current_team_id: null,
         profile_photo_path: null,
         created_at: "2020-10-06 17:02:31",
         updated_at: "2020-10-06 17:02:31",
         pivot: Illuminate\Database\Eloquent\Relations\Pivot {#3457
           user_id: 1,
           following_user_id: 6,
         },
       },
     ],
   }
```

ブラウザ確認してみても、正常に反映されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235741/6ccea665-5011-73e3-402e-b24dc189806e.png)


以上です。