フォロー機能の実装① ~Laravel~

#概要
Laravel x Vue.js(Vuex)でSPAに対応したフォロー機能を実装します。
今回はLaravel部分だけの実装になります。

フロントの実装はこちら→[フォロー機能の実装② ~フロントエンド~](https://qiita.com/kke1229/items/f0a890011a5874258e1f)

最終的なUIはこんな感じ↓
![ダウンロード (3).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643906/8d042348-0d6c-8979-6058-55d7001f8862.gif)
フォローボタンを押したらフォローできて、フォロー解除を押したらフォロー解除するだけです。
##バージョン
Laravel 8.12
Vue.js 2.5.17
Vuex 3.6.0
Vue Router 3.4.9
#実装
##テーブルの作成
```xxxx_xx_xx_xxxxxxx_create_follow_users_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateFollowUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('follow_users', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->unsignedBigInteger('followed_user_id')->index();
            $table->unsignedBigInteger('following_user_id')->index();
            $table->timestamps();

            $table->foreign('followed_user_id')
                ->references('id')
                ->on('users')
                ->cascadeOnDelete();
            $table->foreign('following_user_id')
                ->references('id')
                ->on('users')
                ->cascadeOnDelete();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('follow_users');
    }
}

```
```
mysql> desc follow_users;
+-------------------+-----------------+------+-----+---------+----------------+
| Field             | Type            | Null | Key | Default | Extra          |
+-------------------+-----------------+------+-----+---------+----------------+
| id                | bigint unsigned | NO   | PRI | NULL    | auto_increment |
| followed_user_id  | bigint unsigned | NO   | MUL | NULL    |                |
| following_user_id | bigint unsigned | NO   | MUL | NULL    |                |
| created_at        | timestamp       | YES  |     | NULL    |                |
| updated_at        | timestamp       | YES  |     | NULL    |                |
+-------------------+-----------------+------+-----+---------+----------------+
5 rows in set (0.19 sec)
```
>followed_user_id:フォローされているユーザー
following_user_id:フォローしているユーザー

##Userモデルに追加
```Models/User.php
<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name',
        'email',
        'password',
        'login_id',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];
  /*
   *フォローされているユーザーを取得
   */
    public function followUsers()
    {
        return $this->belongsToMany(
            'App\Models\User',
            'follow_users',
            'followed_user_id',
            'following_user_id'
        );
    }
  /*
   *フォローしているユーザーを取得
   */

    public function follow()
    {
        return $this->belongsToMany(
            'App\Models\User',
            'follow_users',
            'following_user_id',
            'followed_user_id'
        );
    }
   }
}
```
>多対多のテーブルになるので、両方ともbelongsToManyで取得する。

##コントローラ の作成
```FollowUserController.php
<?php

namespace App\Http\Controllers;

use App\Models\FollowUser;
use App\Models\User;
use Illuminate\Http\Request;

class FollowUserController extends Controller
{
    //フォローする
    public function follow(Request $request)
    {
        FollowUser::firstOrCreate([
            'followed_user_id' => $request->post_user,
            'following_user_id' => $request->auth_user
        ]);
        return true;
    }
    //フォロー解除する
    public function unfollow(Request $request)
    {
        $follow = FollowUser::where('followed_user_id', $request->post_user)
            ->where('following_user_id', $request->auth_user)
            ->first();
        if ($follow) {
            $follow->delete();
            return false;
        }
    }
}

```
>unfollow()では先にこのレコードが存在するのか確認してから削除処理を行いました。
返り値をbooleanで返すことで、フロント実装の際にフォローしているかしていないかの確認をします。

#まとめ
これでバックエンドの処理は終わりなので、次はフロントの処理を書こうと思います。