Laravel8 livewire ロールでログイン後のリダイレクト先を変更

前回こちらの記事で、ロールの設定についてご紹介しました。
https://qiita.com/yyy752/items/9f758a5266b2187179b2

今回は設定したロールを使って、ユーザー権限ごとにログイン後のリダイレクト先を変更する方法についてご紹介しようと思います！
また、前回はロールを数字で設定したのですが、実際に実装してみた結果、文字列で設定した方が個人的にやりやすかったので、今回はロールを`user`と`admin`で設定した程でリダイレクト先の変更をしていきます！

僕自身、livewireの修正にかなり苦戦したので、こちらの記事が少しでも参考になれば幸いです。

##roleカラムを数字から文字列に変更
先ずは、前回設定したroleカラムを数字から文字列で管理するよう修正します。
前回作成したマイグレーションファイルを修正して、`php artisan migrate:fresh`を実行してデータベースに変更点を反映させます。

1.前回作成した/database/migrations/add_column_role_users_table.phpを編集

```/database/migrations/2021_08_230109_add_column_role_users_table.php
<?php

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

class AddColumnRoleUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        //roleカラムをstring型でpasswordカラムの後に追加。更にインデックスを付与。
        Schema::table('users', function (Blueprint $table) {
            $table->string('role')->default('user')->after('password')->index('index_role')->comment('ロール');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropColumn('role');
        });
    }
}
```
2.DBに反映

```
php artisan migrate:fresh
Or
php artisan migrate:refresh
```

5.ユーザーアカウントと管理者アカウントを作成
ロールはデフォルトでuserになるよう設定したので、管理者アカウントのロールはデータベースから手動でadminに変更するか、シーダーからroleカラムをadminにしたアカウントを作成してください。

##ゲートの設定

```/app/Providers/AuthServiceProvider.php
<?php

namespace App\Providers;

use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        'App\Models\Model' => 'App\Policies\ModelPolicy',
    ];

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        // 管理者以上に許可
        Gate::define('admin-higher', function ($user) {
            return $user->role === 'admin';
        });
        // 一般ユーザ以上に許可
        Gate::define('user-higher', function ($user) {
            return $user->role === 'user';
        });
    }
}
```

##リダイレクト先の変更
下記のように修正していきます。
自身のプロジェクトにないファイルは随時作成してください。

```/app/Providers/RouteServiceProvider.php
public const HOME = 'redirects';
```

```/routes/web.php
Route::get('redirects', 'App\Http\Controllers\LoginController@index');
```

```/app/Http/Controllers/LoginController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Requests\ValidateRequest;
use Illuminate\Support\Facades\Auth;

class LoginController extends Controller
{
    public function index()
    {
        $role = Auth::user()->role;
        $checkrole = explode(',', $role);
        if (in_array('admin', $checkrole)) {
            return redirect('/admin/list');
        } elseif(in_array('user', $checkrole)) {
            return redirect('/list');
        }

    }
}
```

```/app/Http/Response/LoginResponse.php
<?php

namespace App\Http\Responses;

use Laravel\Fortify\Contracts\LoginResponse as LoginResponseContract;

class LoginResponse implements LoginResponseContract
{
    /**
     * Create an HTTP response that represents the object.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function toResponse($request)
    {
        $role = \Auth::user()->role;

        if ($request->wantsJson()) {
            return response()->json(['two_factor' => false]);
        }

        switch ($role) {
            case 'admin':
                return redirect('/admin/list');
            case 'user':
                return redirect('/list');
            default:
                return redirect('/login');
        }
    }
}
```

```/app/Http/Response/TwoFactorLoginResponse.php
<?php

namespace App\Http\Responses;

use Laravel\Fortify\Contracts\TwoFactorLoginResponse as TwoFactorLoginResponseContract;

class TwoFactorLoginResponse implements TwoFactorLoginResponseContract
{
    /**
     * Create an HTTP response that represents the object.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function toResponse($request)
    {
        $role = \Auth::user()->role;

        if ($request->wantsJson()) {
            return response('', 204);
        }

        switch ($role) {
            case 'admin':
                return redirect('/admin/list');
            case 'user':
                return redirect('/list');
            default:
                return redirect('/login');
        }
    }
}
```

```/app/Providers/FortifyServiceProvider.php
<?php

namespace App\Providers;

use App\Actions\Fortify\CreateNewUser;
use App\Actions\Fortify\ResetUserPassword;
use App\Actions\Fortify\UpdateUserPassword;
use App\Actions\Fortify\UpdateUserProfileInformation;
use Illuminate\Cache\RateLimiting\Limit;
//use Illuminate\Auth\Notifications\ResetPassword;  //追加
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\ServiceProvider;
use Laravel\Fortify\Fortify;
use Laravel\Fortify\Contracts\LoginResponse as LoginResponseContract;
use Laravel\Fortify\Contracts\TwoFactorLoginResponse as TwoFactorLoginResponseContract;
use App\Http\Responses\LoginResponse;
use App\Http\Responses\TwoFactorLoginResponse;

class FortifyServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        // デフォルトのFortifyルーティングを無効化
        //Fortify::ignoreRoutes();
        $this->registerResponseBindings();
    }

    /**
     * Register the response bindings.
     *
     * @return void
     */
    protected function registerResponseBindings()
    {
        $this->app->singleton(LoginResponseContract::class, LoginResponse::class);
        $this->app->singleton(TwoFactorLoginResponseContract::class, TwoFactorLoginResponse::class);
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Fortify::createUsersUsing(CreateNewUser::class);
        Fortify::updateUserProfileInformationUsing(UpdateUserProfileInformation::class);
        Fortify::updateUserPasswordsUsing(UpdateUserPassword::class);
        Fortify::resetUserPasswordsUsing(ResetUserPassword::class);

        RateLimiter::for('login', function (Request $request) {
            return Limit::perMinute(5)->by($request->email.$request->ip());
        });

        RateLimiter::for('two-factor', function (Request $request) {
            return Limit::perMinute(5)->by($request->session()->get('login.id'));
        });
    }
}
```

##まとめ
これでユーザー権限ごとにログイン後のリダイレクト先を変更することができました！
あとは、こちらを参考に自身の想定通りにリダイレクトされるよう修正してもらえればと思います。

参考サイト
「laravel8 jetstreamのfortifyを使ってmulti authログインを実現する。」
https://syoblog.com/laravel8-multi-auth/

「Laravel8でCMSを作るチュートリアル(6) ユーザーロール（権限）の設定」
https://www.webopixel.net/php/1675.html