1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Posted at

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

手順1: まず、以下がフォローリストの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>

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

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

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

php artisan make:migration create_follows_table

手順4: マイグレーションファイルを設定します。
ユーザー間及びフォローしているユーザー間の関係を設定する為には、'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');
        });
    }

手順5: マイグレーションします。

php artisan migrate

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

image.png

因みに、既に作ってあるusersテーブルはこのような感じ。
image.png

手順7: これから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');
    }

手順8: 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: [],

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

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');
    }

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

php artisan migrate:fresh

手順11: 新たにuserテーブルにデータを入れていきます。このような感じ。(id1だけはブラウザのregisterページから手動で登録して、その他はFactory機能で登録しました。)
image.png

手順12: 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);

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

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

テーブルには以下のように入ります。
image.png
ブラウザで確認(id1のアカウント)すると、ちゃんと表示もされています。
image.png

手順14: id1がid6をフォローしてみます。

$yumiko = App\Models\User::find(6);
$me->follow($yumiko);

手順15: 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

以上です。

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?