【Laravel】世界一シンプルで簡単なフォロー機能の実装(リレーションなし)

こんにちは、わいまつです。 今回は、LaravelでTwitterのようなフォロー機能を実装していきたいと思います。

前回の準備編をまだご覧になっていない方はこちらからどうぞ。

こちらの記事はLaravelでフォロー機能を実装するにあたり、いくつかのパターンで紹介します。 パターン1では、リレーションメソッドなしで実装する例になります。 全3パターンを考えていて、それぞれの概要は以下になります。

パターン 概要
パターン1 (難易度★☆☆)

リレーションメソッドなしでシンプルに実装

パターン2 (難易度★★☆) belongsToを使って実装(準備中)
パターン3 (難易度★★★) belongsToManyを使って実装(準備中)

Laravelの初学者の方や、違いを比較検討したいかたはぜひ御覧ください。

フォロー機能の実装(パターン1)

概要

こちらのパターンでは、リレーションメソッド(hasMany、belongsToなど)を用いずに、シンプルで簡単なフォロー機能を実装します。

複雑な機能はいらない!単純にフォローしているかどうか表示したい!などの場合に役立つと思います。

以下のようなメリット・デメリットがあります。

メリット

  • リレーションメソッドを使わないため実装がシンプル
  • フォロー機能のイメージをつかめる

デメリット

  • 関係を持たないため、紐付いたデータの取得がやりにくい

完成イメージ

まず、完成イメージはこちらになります。

実装

さて、ここから実際にフォロー機能を実装していきます。

1.ルーティングの設定

今回はパートを3つに分ける都合上、「norelation」というパスで実装します。

同時にフォローボタンを押した際のルートも書いておきます。

/belongs-to/routes/web.php

<?php

use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});

Auth::routes();

Route::get('/home', 'HomeController@index')->name('home');
Route::get('/norelation', 'HomeController@norelation');
Route::get('/follow', 'HomeController@follow');

2.コントローラーにメイン処理を書く

コントローラーに処理を書いていきます。

アクション名もnorelationとしています。

/belongs-to/app/Http/Controllers/HomeController.php


<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
use App\User;
use App\Follower;

class HomeController extends Controller
{
    /**
     * Create a new controller instance.
     *
     * @return void
     */

    public function __construct()
    {
        $this->middleware('auth');
    }

    /**
     * Show the application dashboard.
     *
     * @return \Illuminate\Contracts\Support\Renderable
     */

    public function norelation()
    {
        // ログインユーザーIDの取得
        $login_user = Auth::User()->id;
        // ユーザー一覧の取得(自分以外)
        $users = DB::table('users')->where('id', '<>', $login_user)->get();

        // フォローしているリストの作成
        $following_list = DB::table('followers')->where('following_id', $login_user)->get();
        $arr_following =[];
        foreach ($following_list as $following_user) {
            $arr_following[] = $following_user->followed_id;
        }

        // フォローされているリストの作成
        $followed_list = DB::table('followers')->where('followed_id', $login_user)->get();
        $arr_followed =[];
        foreach ($followed_list as $followed_user) {
            $arr_followed[] = $followed_user->following_id;
        }

        return view('norelation', compact('users', 'arr_followed', 'arr_following'));
    }
}

前述の通り、リレーションメソッドを使わないため、フォローしているユーザーの一覧配列とフォローされているユーザーの一覧を用意します。

その配列にユーザーIDを入れていくことでフォローされているかどうかを判定します。

3.blade.phpの作成

blade側を見ていきましょう。

/belongs-to/resources/views/norelation.blade.php


@extends('layouts.app')
@section('content')
<div class="container">
  <div class="row justify-content-center">
    <div class="col-md-8">
      <table border="1">
        <tr style="background:#AAA"><th>ID</th><th>ユーザー名</th><th>フォローしているか</th><th>フォローされているか</th></tr>
        @foreach($users as $user)
          <tr>
            <td>{{ $user->id }}</td>
            <td>{{ $user->name }}</td>
            <td>
            <a href="{{ action('HomeController@follow', ['id' => $user->id]) }}">
            @if (!empty($arr_following))
              @if(in_array($user->id, $arr_following))
                <input type="button" value="フォローをはずす">
              @else
                <input type="button" value="フォロー">
              @endif
            @else
              <input type="button" value="フォロー">
            @endif
            </a>
            </td>
            <td>
              @if (!empty($arr_followed))
                @if(in_array($user->id, $arr_followed))
                  フォローされています
                @else
                  フォローされていません
                @endif
              @else
                フォローされていません
              @endif
            </td>
          </tr>
        @endforeach
      </table>
    </div>
  </div>
</div>
@endsection

 

コントローラーで作成した、配列のなかに$user->idがあれば、フォロー中orフォローされているということになります。

フォロー中かどうかに関係なくボタンを押したときに、followアクションを呼びます。※一部抜粋

/belongs-to/app/Http/Controllers/HomeController.php


public function follow(Request $request)
    {
        $target_id = $request->id;
        $login_user = Auth::User()->id;
        // dd($target_id);
        $status = DB::table('followers')->where('following_id', $login_user)
                                            ->where('followed_id', $target_id)->exists();


        if ($status) {
            // 存在する = フォローされている状態なので、フォローを外す
            // フォローを外すには、該当のレコードを削除する
            DB::table('followers')->where('following_id', $login_user)
                                            ->where('followed_id', $target_id)->delete();

        } else {
            // 存在しない = フォローされていない状態なので、フォローする
            // フォローをするには、レコードを作成
            $follow = new Follower;
            $follow->following_id = $login_user;
            $follow->followed_id = $target_id;
            $follow->save();
        }
        return redirect('norelation');
    }

ボタンを押された$user->idをリクエストパラーメータに含め、処理しています。

レコードの有無(exitst())によって、フォロー化、フォローを外すか決定しています。

 

まとめ

今回はリレーションメソッドなし編ということで、次回はbelongsToを使った実装を投稿予定です。

パターン 概要
パターン1 (難易度★☆☆)

リレーションメソッドなしでシンプルに実装

パターン2 (難易度★★☆) belongsToを使って実装(準備中)
パターン3 (難易度★★★) belongsToManyを使って実装(準備中)

Twitterでは日々の気づき等もつぶやいているのでぜひご登録ください。よければコメント、記事のシェア等してくれたら嬉しいです。ではまた。

返信を残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です