【Laravel7でユーザー認証_6】ユーザーの情報を表示・変更する設定画面を作成する

# はじめに

Laravelでユーザー認証した後、ログインユーザーの登録情報を表示・変更する設定画面を作成する手順をまとめます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262236/c558ece3-d222-29bf-d44b-a516880e6758.png" width="600">

URLと対応する内容はこのような仕様にします。

|URL|処理内容|
|:--|:--|
|/setting|ユーザーの登録情報表示|
|/setting/name|名前の変更フォーム表示・変更処理|
|/setting/email|メールアドレスの変更フォーム表示・変更処理|
|/setting/username|ユーザー名の変更フォーム表示・変更処理|
|/setting/password|パスワードの変更フォーム表示・変更処理|
|/setting/deactive|アカウント削除のフォーム表示・削除処理|

※細かいことはいいからソースが見たい→[まとめのソース](#まとめのソース) 

# 環境

XAMPP環境でLaravelが使えるように設定してあります。

- Windows10 Pro 64bit
- PHP 7.3.18
- Laravel 7.12.0
- MariaDB 10.1.32

また、Laravelプロジェクトは以下の手順で作業を進めており、パスワード変更フォームを作成するところまでできていること前提となっています。

- [【Laravel7でユーザー認証_1】基本のき](https://qiita.com/crosawassant/items/bf3982666b6333bcb8c8)
- [【Laravel7でユーザー認証_2】ユーザー認証を日本語化](https://qiita.com/crosawassant/items/d1f4c5c93f30afa9eb65)
- [【Laravel7でユーザー認証_3】ユーザー認証をメールアドレスからユーザー名に変更する](https://qiita.com/crosawassant/items/2464db8a0fe1c603401a)
- [【Laravel7でユーザー認証_4】パスワード変更フォームを作成する](https://qiita.com/crosawassant/items/04242c8d7a12346dcc20)
- [【Laravel7でユーザー認証_5】ユーザーを倫理削除（SoftDelete）する](https://qiita.com/crosawassant/items/a6e3e9b1aedf566b2d27)

# 実装手順

##ユーザー情報を表示する設定画面の作成

###コントローラの作成

コマンドでコントローラを作成します。
今回は「SettingController」というコントローラ名にしました。

```
$ php artisan make:controller SettingController
```

`app/Http/Controllers/` の中に、`SettingController.php` が出来上がります。

###ルーティングの設定

/setting にアクセスがあったら、`SettingController` の `index` メソッドを実行するようにルーティングを設定します。
ルーティング名は `setting` と指定しました。

```diff:/routes/web.php
+ Route::get('/setting', 'SettingController@index')->name('setting');
```

###viewの作成
viewは、`setting` というディレクトリにまとめたいと思うので、`resources/views` の中に `setting` というディレクトリを新たに作成します。
作成した`setting` ディレクトリの中に `index.blade.php` を作成しました。

```php:resources/views/setting/index.blade.php
@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('UserInfo') }}</div>

                <div class="card-body">
                    @if (session('status'))
                        <div class="alert alert-success" role="alert">
                            {{ session('status') }}
                        </div>
                    @endif
                    <div class="list-group mb-3" style="max-width:400px; margin:auto;">
                      <a href="{{ route('name.form') }}" class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
                        <dl class="mb-0">
                          <dt>{{ __('Name') }}</dt>
                          <dd class="mb-0">{{ $auth->name }}</dd>
                        </dl>
                        <div><i class="fas fa-chevron-right"></i></div>
                      </a>

                      <a href="{{ route('username.form') }}" class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
                        <dl class="mb-0">
                          <dt>{{ __('UserName') }}</dt>
                          <dd class="mb-0">{{ $auth->username }}</dd>
                        </dl>
                        <div><i class="fas fa-chevron-right"></i></div>
                      </a>

                      <a href="{{ route('email.form') }}" class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
                        <dl class="mb-0">
                          <dt>{{ __('E-Mail Address') }}</dt>
                          <dd class="mb-0">{{ $auth->email }}</dd>
                        </dl>
                        <div><i class="fas fa-chevron-right"></i></div>
                      </a>

                      <a href="{{ route('password.form') }}" class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
                        <dl class="mb-0">
                          <dt>{{ __('Password') }}</dt>
                          <dd class="mb-0">********</dd>
                        </dl>
                        <div><i class="fas fa-chevron-right"></i></div>
                      </a>
                </div>
                <div class="list-group" style="max-width:400px; margin:auto;">
                    <a href="{{ route('deactive.form') }}" class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
                      <div>{{ __('Deactive') }}</div>
                      <div><i class="fas fa-chevron-right"></i></div>
                    </a>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection
```

パスワード変更フォームは `route('password.form')` 、アカウント削除フォームは `route('deactive.form')` でリンク先が取得できますが、他のフォームはまだ準備ができていないので、`#` にしておきます。

####アイコンフォント（FontAwsome）の読み込み

view内で、アイコンフォント（FontAwsome）を使っているので、npmでインストール・コンパイルします。

```:インストール
$ npm install @fortawesome/fontawesome-free --save-dev
```

```diff:resouces/sass/app.scss
  // Bootstrap
  @import '~bootstrap/scss/bootstrap';

+ // Font Awesome
+ @import '~@fortawesome/fontawesome-free/scss/fontawesome';
+ @import '~@fortawesome/fontawesome-free/scss/solid';
+ @import '~@fortawesome/fontawesome-free/scss/regular';
+ @import '~@fortawesome/fontawesome-free/scss/brands';
```

```:コンパイル
$ npm run dev
```

####翻訳ファイルに追加

view内で使った翻訳文字をja.jsonに追加します。

```diff:resource/lang/ja.json
-     "Your password has been changed.": "パスワードが変更されました。"
+     "Your password has been changed.": "パスワードが変更されました。",
+     "UserInfo": "ユーザー情報"
  }
```

###コントローラにメソッド追加

`SettingController` に、ルーティングで指定した`index` メソッドを追加します。
`index` メソッド内では、作成したview（setting/index.blade.php）が表示されるように指定します。
データベースに登録されたユーザーの情報もviewに表示させたいので、第二引数にユーザーの情報を渡します。

また、ログインしていない場合はログイン画面を表示させたいので、コンストラクタ（__construct）でAuthミドルウェアを呼び出すように設定します。

```diff:app/Http/Controllers/SettingController.php
  <?php
  
  namespace App\Http\Controllers;
  
  use Illuminate\Http\Request;
+ use Illuminate\Support\Facades\Auth;

  class SettingController extends Controller
  {
-     //
+     public function __construct()
+     {
+         $this->middleware('auth');
+     }
+ 
+     public function index()
+     {
+         $auth = Auth::user();
+         return view('setting\index', ['auth' => $auth]);
+     }
  }
```
###一旦確認

http://127.0.0.1:8000/setting にアクセスして、表示ができるかどうか確認します。

▼このような画面になるはず…そして「パスワード」と「アカウント削除」はクリックして変更フォームが開くはず…
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262236/c558ece3-d222-29bf-d44b-a516880e6758.png" width="600">


##パスワード変更フォーム・アカウント削除のURLを変更

パスワード変更フォームは現在 /password/change となっていますが、/setting/password にしたいので、ルーティングを変更します。
同じように、アカウント削除のURLも /setting/deactive に変更します。

```diff:routes/web.php
- Route::get('/password/change', 'Auth\ChangePasswordController@showChangePasswordForm')->name('password.form');
- Route::post('/password/change', 'Auth\ChangePasswordController@changePassword')->name('password.change');
+ Route::get('/setting/password', 'Auth\ChangePasswordController@showChangePasswordForm')->name('password.form');
+ Route::post('/setting/password', 'Auth\ChangePasswordController@changePassword')->name('password.change');
-  
- Route::get('/deactive', 'Auth\DeactiveController@showDeactiveForm')->name('deactive.form');
- Route::post('/deactive', 'Auth\DeactiveController@deactive')->name('deactive');
+ Route::get('/setting/deactive', 'Auth\DeactiveController@showDeactiveForm')->name('deactive.form');
+ Route::post('/setting/deactive', 'Auth\DeactiveController@deactive')->name('deactive');
```

view内で `<a href="{{ url('/setting/password') }}">`と直接指定してしまうと、URL変更時に修正箇所を探して手作業で修正しなければなりません。ルーティング設定時につけた名前で`「<a href="{{ route('password.change') }}">」` と指定していれば、Laravelが自動でリンク先を変更してくれます。

##氏名変更フォームの作成

氏名をクリックした際に、パスワードと同じように変更フォームが表示されるようにします。
コントローラは、`SettingController` を使うことにします。

###ルーティングの設定

以下の仕様で、ルーティングを設定します。

- /setting/name にアクセスがあったら、「SettingController」コントローラの「showChangeNameForm」メソッドを実行。
- ユーザー名変更の処理（POST）の場合は、「SettingController」コントローラの「changeName」メソッドを実行。

それぞれのルーティングには、「name.form」、「name.change」という名前を付けました。

```diff:/routes/web.php
+ Route::get('/setting/name', 'SettingController@showChangeNameForm')->name('name.form');
+ Route::post('/setting/name', 'SettingController@changeName')->name('name.change');
```

###viewの作成
`resources/views/setting` の中に `name.blade.php` を作成します。

```php:resources/views/setting/name.blade.php
@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Change Name') }}</div>

                <div class="card-body">
                    <form method="POST" action="{{ route('name.change') }}">
                        @csrf

                        <div class="form-group row">
                            <label for="name" class="col-md-4 col-form-label text-md-right">{{ __('Name') }}</label>

                            <div class="col-md-6">
                                <input id="name" type="text" class="form-control @error('name') is-invalid @enderror" name="name" value="{{ old('name', $auth->name) }}" required autocomplete="name">

                                @error('name')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

                        <div class="form-group row mb-0">
                            <div class="col-md-6 offset-md-4">
                                <button type="submit" class="btn btn-primary">
                                    {{ __('Change Name') }}
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

```
####翻訳ファイルに追加

view内で使った翻訳文字をja.jsonに追加します。

```diff:resource/lang/ja.json
-     "UserInfo": "ユーザー情報"
+     "UserInfo": "ユーザー情報",
+     "Change Name": "氏名変更"
  }
```

###FormRequest の設定

名前変更時のバリデーションチェックをFormRequestで処理するよう、`ChangeNameRequest` というFormRequestを作成します。

```
$ php artisan make:request ChangeNameRequest
```

作成された `app/Http/Request/ChangeNameRequest.php` について、バリデーションルールを追加します。

```diff:app/Http/Request/ChangeNameRequest.php
  <?php
  
  namespace App\Http\Requests;

  use Illuminate\Foundation\Http\FormRequest;
+ use Illuminate\Contracts\Validation\Validator;
+ use Illuminate\Http\Exceptions\HttpResponseException;

  class ChangeNameRequest extends FormRequest
  {
      /**
       * Determine if the user is authorized to make this request.
       *
       * @return bool
       */
      public function authorize()
      {
-         return false;
+         return true;
      }

      /**
       * Get the validation rules that apply to the request.
       *
       * @return array
       */
      public function rules()
      {
          return [
-             //
+             'name' => ['required', 'string', 'max:255']
          ];
      }
  }
```

###コントローラにメソッド追加

`SettingController` に、ルーティングで指定した `showChangeNameForm` メソッド（変更フォーム表示用）と`changeNname`（ユーザー名変更処理用）を追加します。

`showChangeNameForm` メソッド内では、作成したview（setting/name.blade.php）が表示されるように指定します。
`changeName` メソッドでは、先ほど作成したFormRequestを使用するように指定します。

```diff:app/Http/Controllers/SettingController.php
  <?php

  namespace App\Http\Controllers;

  use Illuminate\Http\Request;
  use Illuminate\Support\Facades\Auth;
+ use App\Http\Requests\ChangeNameRequest;

===（略）===

+ 
+     public function showChangeNameForm()
+     {
+         $auth = Auth::user();
+         return view('setting\name', ['auth' => $auth]);
+     }
+ 
+     public function changeName(ChangeNameRequest $request)
+     {
+       //ValidationはChangeNameRequestで処理
+       //氏名変更処理
+       $user = Auth::user();
+       $user->name = $request->get('name');
+       $user->save();
+
+       //homeにリダイレクト
+       return redirect()->route('setting')->with('status', __('Your name has been changed.'));
+     }
```

####翻訳ファイルに追加

```diff:resources/lang/ja.json
-     "Change Name": "氏名変更"
+     "Change Name": "氏名変更",
+     "Your name has been changed.": "氏名が変更されました。"
  }
```

###設定画面からリンクする

ユーザーの登録情報表示の画面から、氏名変更フォームへリンクします。

```diff:resouces/views/setting/index.blade.php
-                       <a href="#" class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
+                       <a href="{{ route('name.form') }}" class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
                          <dl class="mb-0">
                            <dt>{{ __('Name') }}</dt>
                            <dd class="mb-0">{{ $auth->name }}</dd>
                          </dl>
                          <div><i class="fas fa-chevron-right"></i></div>
                        </a>
```

###一旦確認

http://127.0.0.1:8000/setting にアクセスして、氏名をクリックして変更ができるかどうか確認します。

▼私がしょっちゅう出すエラー例
<dl><dt>Method App\Http\Controllers\SettingController::showChangeNameForm does not exist.</dt>
<dd>コントローラに該当のメソッドを追加し忘れているか、スペルミスしているかです。`SettingController.php` で `showChangeNameForm` があるかどうか、スペルミスしていないかチェックします。</dd>
<dt>Target class [App\Http\Controllers\ChangeNameRequest] does not exist.</dt>
<dd>作成したRequestFormが読み込めていなさそうです。`SettingController.php` で `use App\Http\Requests\ChangeNameRequest;` が抜けていないでしょうか。</dd>
<dt>Route [name.form] not defined. </dt>
<dd>viewで指定したルート名（name.form）が定義されていないようです。`routes/web.php` できちんとルート名の定義をしているか確認します。</dd>
<dt>エラーは出ないけど変更されない・リダイレクトしない</dt>
<dd>formの送信先が違っていたとき、エラーが表示されず処理も進まないことがありました。`resouces/views/setting/name.blade.php` の<form>のaction先が `{{ route('name.change') }}` になっているか確認します。</dd>
</dl>

##メールアドレス変更フォームの作成

氏名と同じ手順で、メールアドレスをクリックした際に変更フォームが表示されるようにします。

###ルーティングの設定

```diff:/routes/web.php
+ Route::get('/setting/email', 'SettingController@showChangeEmailForm')->name('email.form');
+ Route::post('/setting/email', 'SettingController@changeEmail')->name('email.change');
```

###viewの作成

```php:resources/views/setting/email.blade.php
@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Change Email') }}</div>

                <div class="card-body">
                    <form method="POST" action="{{ route('email.change') }}">
                        @csrf

                        <div class="form-group row">
                            <label for="name" class="col-md-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label>

                            <div class="col-md-6">
                                <input id="email" type="text" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email', $auth->email) }}" required autocomplete="email">

                                @error('email')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

                        <div class="form-group row mb-0">
                            <div class="col-md-6 offset-md-4">
                                <button type="submit" class="btn btn-primary">
                                    {{ __('Change Email') }}
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection
```

###FormRequest の設定

```
$ php artisan make:request ChangeEmailRequest
```

メールアドレスについては、「重複不可」かつ「本人が同じメールアドレスで更新した場合はバリデーションを通す」という仕様にしたいので、FormRequestのrulesに少しコツがいります。
`ignore`メソッドを使って、ログイン中しているユーザーのIDをuniqueチェックから除外します。

```diff:app/Http/Request/ChangeEmailRequest.php
  <?php

  namespace App\Http\Requests;

  use Illuminate\Foundation\Http\FormRequest;
+ use Illuminate\Contracts\Validation\Validator;
+ use Illuminate\Http\Exceptions\HttpResponseException;
+ use Illuminate\Validation\Rule;
+ use Illuminate\Support\Facades\Auth;

  class ChangeEmailRequest extends FormRequest
  {
      /**
       * Determine if the user is authorized to make this request.
       *
       * @return bool
       */
      public function authorize()
      {
-         return false;
+         return true;
      }

      /**
       * Get the validation rules that apply to the request.
       *
       * @return array
       */
      public function rules()
      {
          $user = Auth::user();
          return [
-             //
+             'email' => ['required', 'string', 'email', 'max:255', Rule::unique('users', 'email')->ignore(Auth::id())->whereNull('deleted_at')]
          ];
      }
  }
```

###コントローラにメソッド追加

```diff:app/Http/Controllers/SettingController.php
  <?php

  namespace App\Http\Controllers;

  use Illuminate\Http\Request;
  use Illuminate\Support\Facades\Auth;
  use App\Http\Requests\ChangeNameRequest;
+ use App\Http\Requests\ChangeEmailRequest;

===（略）===
+ 
+     public function showChangeEmailForm()
+     {
+         $auth = Auth::user();
+         return view('setting\email', ['auth' => $auth]);
+     }
+     
+     public function changeEmail(ChangeEmailRequest $request)
+     {
+       //ValidationはChangeUsernameRequestで処理
+       //メールアドレス変更処理
+       $user = Auth::user();
+       $user->email = $request->get('email');
+       $user->save();
+ 
+       //homeにリダイレクト
+       return redirect()->route('setting')->with('status', __('Your email address has been changed.'));
+     }
  }
```

###翻訳ファイルに追加

```diff:resources/lang/ja.json
-     "Your name has been changed.": "氏名が変更されました。"
+     "Your name has been changed.": "氏名が変更されました。",
+     "Change Email": "メールアドレス変更",
+     "Your email address has been changed.": "メールアドレスが変更されました。"
  }
```

###設定画面からリンクする
```diff:resouces/views/setting/index.blade.php
-                       <a href="#" class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
+                       <a href="{{ route('email.form') }}" class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
                          <dl class="mb-0">
                            <dt>{{ __('E-Mail Address') }}</dt>
                            <dd class="mb-0">{{ $auth->email }}</dd>
                          </dl>
                          <div><i class="fas fa-chevron-right"></i></div>
                        </a>
```

##ユーザー名変更フォームの作成

ユーザー名の変更はメールアドレスとほぼ同じ内容なので割愛します。
まとめのソースの方でご確認ください。



本当は、「メールアドレス変更のリクエストがきても、メール認証が完了するまでは変更されない」という仕様にしたいので、もう少し調べる必要がありそうです。
次回に持ち越しとします。

#まとめのソース
<details><summary>View（resources/views/setting/index.blade.php）</summary><div>

```php:resources/views/setting/index.blade.php
@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('UserInfo') }}</div>

                <div class="card-body">
                    @if (session('status'))
                        <div class="alert alert-success" role="alert">
                            {{ session('status') }}
                        </div>
                    @endif
                    <div class="list-group" style="max-width:400px; margin:auto;">
                      <a href="{{ route('name.form') }}" class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
                        <dl class="mb-0">
                          <dt>{{ __('Name') }}</dt>
                          <dd class="mb-0">{{ $auth->name }}</dd>
                        </dl>
                        <div><i class="fas fa-chevron-right"></i></div>
                      </a>

                      <a href="{{ route('username.form') }}" class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
                        <dl class="mb-0">
                          <dt>{{ __('UserName') }}</dt>
                          <dd class="mb-0">{{ $auth->username }}</dd>
                        </dl>
                        <div><i class="fas fa-chevron-right"></i></div>
                      </a>

                      <a href="#" class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
                        <dl class="mb-0">
                          <dt>{{ __('E-Mail Address') }}</dt>
                          <dd class="mb-0">{{ $auth->email }}</dd>
                        </dl>
                        <div><i class="fas fa-chevron-right"></i></div>
                      </a>

                      <a href="{{ route('password.form') }}" class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
                        <dl class="mb-0">
                          <dt>{{ __('Password') }}</dt>
                          <dd class="mb-0">********</dd>
                        </dl>
                        <div><i class="fas fa-chevron-right"></i></div>
                      </a>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection
```
</div></details>

<details><summary>View（resources/views/setting/name.blade.php）</summary><div>

```php:resources/views/setting/name.blade.php
@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Change Name') }}</div>

                <div class="card-body">
                    <form method="POST" action="{{ route('name.change') }}">
                        @csrf

                        <div class="form-group row">
                            <label for="name" class="col-md-4 col-form-label text-md-right">{{ __('Name') }}</label>

                            <div class="col-md-6">
                                <input id="name" type="text" class="form-control @error('name') is-invalid @enderror" name="name" value="{{ old('name', $auth->name) }}" required autocomplete="name">

                                @error('name')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

                        <div class="form-group row mb-0">
                            <div class="col-md-6 offset-md-4">
                                <button type="submit" class="btn btn-primary">
                                    {{ __('Change Name') }}
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

```
</div></details>


<details><summary>View（resources/views/setting/email.blade.php）</summary><div>

```php:resources/views/setting/email.blade.php
@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Change Email') }}</div>

                <div class="card-body">
                    <form method="POST" action="{{ route('email.change') }}">
                        @csrf

                        <div class="form-group row">
                            <label for="name" class="col-md-4 col-form-label text-md-right">{{ __('Email') }}</label>

                            <div class="col-md-6">
                                <input id="email" type="text" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email', $auth->email) }}" required autocomplete="email">

                                @error('email')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

                        <div class="form-group row mb-0">
                            <div class="col-md-6 offset-md-4">
                                <button type="submit" class="btn btn-primary">
                                    {{ __('Change Email') }}
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection
```
</div></details>

<details><summary>View（resources/views/setting/username.blade.php）</summary><div>

```php:resources/views/setting/username.blade.php
@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Change Username') }}</div>

                <div class="card-body">
                    <form method="POST" action="{{ route('username.change') }}">
                        @csrf

                        <div class="form-group row">
                            <label for="name" class="col-md-4 col-form-label text-md-right">{{ __('UserName') }}</label>

                            <div class="col-md-6">
                                <input id="username" type="text" class="form-control @error('username') is-invalid @enderror" name="username" value="{{ old('username', $auth->username) }}" required autocomplete="username">

                                @error('username')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

                        <div class="form-group row mb-0">
                            <div class="col-md-6 offset-md-4">
                                <button type="submit" class="btn btn-primary">
                                    {{ __('Change Username') }}
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection
```
</div></details>

<details><summary>Controller（app/Http/Controllers/SettingController.php）</summary><div>

```php:app/Http/Controllers/SettingController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Http\Requests\ChangeNameRequest;
use App\Http\Requests\ChangeEmailRequest;
use App\Http\Requests\ChangeUsernameRequest;

class SettingController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
    }

    public function index()
    {
        $auth = Auth::user();
        return view('setting\index', ['auth' => $auth]);
    }

    public function showChangeNameForm()
    {
        $auth = Auth::user();
        return view('setting\name', ['auth' => $auth]);
    }
    
    public function changeName(ChangeNameRequest $request)
    {
      //ValidationはChangeUsernameRequestで処理
      //名前変更処理
      $user = Auth::user();
      $user->name = $request->get('name');
      $user->save();

      //homeにリダイレクト
      return redirect()->route('setting')->with('status', __('Your name has been changed.'));
    }

    public function showChangeUsernameForm()
    {
        $auth = Auth::user();
        return view('setting\username', ['auth' => $auth]);
    }
    
    public function changeUsername(ChangeUsernameRequest $request)
    {
      //ValidationはChangeUsernameRequestで処理
      //ユーザー名変更処理
      $user = Auth::user();
      $user->username = $request->get('username');
      $user->save();

      //homeにリダイレクト
      return redirect()->route('setting')->with('status', __('Your username has been changed.'));
    }

    public function showChangeEmailForm()
    {
        $auth = Auth::user();
        return view('setting\email', ['auth' => $auth]);
    }
    
    public function changeEmail(ChangeEmailRequest $request)
    {
      //ValidationはChangeUsernameRequestで処理
      //メールアドレス変更処理
      $user = Auth::user();
      $user->email = $request->get('email');
      $user->save();

      //homeにリダイレクト
      return redirect()->route('setting')->with('status', __('Your email address has been changed.'));
    }
}

```
</div></details>

<details><summary>FormRequest（app/Requests/ChangeNameRequest.php）</summary><div>

```php:app/Requests/ChangeNameRequest.php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;

class ChangeNameRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'name' => ['required', 'string', 'max:255']
        ];
    }
}
```
</div></details>

<details><summary>FormRequest（app/Requests/ChangeEmailRequest.php）</summary><div>

```php:app/Requests/ChangeEmailRequest.php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Validation\Rule;
use Illuminate\Support\Facades\Auth;

class ChangeEmailRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'email' => ['required', 'string', 'email', 'max:255', Rule::unique('users', 'email')->ignore(Auth::id())->whereNull('deleted_at')]
        ];
    }

}
```
</div></details>

<details><summary>FormRequest（app/Requests/ChangeUsernameRequest.php）</summary><div>

```php:app/Requests/ChangeUsernameRequest.php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Validation\Rule;

class ChangeUsernameRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'username' => ['required', 'string', 'max:32', Rule::unique('users', 'email')->whereNull('deleted_at'), 'regex:/^[a-zA-Z0-9-_]+$/']
        ];
    }
}
```
</div></details>

#参考サイト

- [[PHP] Laravel でユーザー認証されている時のユーザー情報の値のとり方や、判定する関数など ｜ memocarilog](https://qiita.com/drafts/d8b434f0bc98455165b4)
- [Laravel+FontAwesomeの使い方 - Qiita](https://qiita.com/algi_nao/items/5d2befae8f367050ae7f)
- [LaravelのuniqueのバリデーションでIDを除外する | SHISHIDO.DEV](https://shishido.dev/laravel-unique-validation/)