Laravel Breezeでregister時にメールの送信確認をする

## やりたいこと
Laravel Breezeの初期設定だとアカウント新規登録時にメールアドレスの確認をしない。
リンク付きメールでアドレスの確認をしてもらいたい。


## smtpサーバーの準備
.envにメールの設定を書いておく。
https://qiita.com/tiro_sx/items/b4cb9a44ebc62821c6f7

## userコントローラー編集
```diff_php: app/Controllers/user.php

+ use Illuminate\Contracts\Auth\MustVerifyEmail;

- class User extends Authenticatable
+ class User extends Authenticatable implements MustVerifyEmail
{
```


## authをverifiedに変える
```diff_php: routes/web.php
middleware('auth')-> //メール認証前でも通す
middleware('verified')-> //メール認証前は通さない
```

これだけでregister時にリンク付きメールでアドレスの確認をしてくれます。
何でもやってくれてありがたい。

## 問題
プロフィールページでメールアドレスを変更する処理が不親切。
（メールアドレスを変更してから認証メールが送られる。
　打ち間違えとかあるから、認証してからメールアドレスを変更したい。）

う～ん。
簡単にやる方法が見つからないから泥臭くやります。

■userテーブルに新メールアドレスとトークンを持たせる。

```php: database/migrations/
<?php

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

return new class extends Migration
{
    public function up(): void
    {
        Schema::table('users', function (Blueprint $table) {
            $table->string('new_email_token')->after('email')->nullable()->comment('メアド変更用');
            $table->string('new_email')->after('email')->nullable()->comment('メアド変更用');
        });
    }

    public function down(): void
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropColumn('new_email_token');
            $table->dropColumn('new_email');
        });
    }
};

```

■プロフィールコントローラーを変える。

```php: app/Contorollers/ProfileController.php
    public function update(ProfileUpdateRequest $request): RedirectResponse
    {
        $oldMail = auth()->user()->email??null;
        $newMail = $request->email??null;
        $request->user()->fill($request->validated());

        if ($request->user()->isDirty('email')) {
            $token = generateRandomString(10);
            $request->user()->email = $oldMail;
            $request->user()->new_email = $newMail;
            $request->user()->new_email_token = $token;

            $url = route('profile.mailUpdate', [auth()->user()->id, $token]);
            $text = "
以下のURLにアクセスしてメールアドレスの変更を完了させてください。
・該当アカウントにログイン中のブラウザでアクセスする必要があります。
・有効期限は1時間です。
$url

当メールに心当たりのない場合はこのメールを破棄してください。
";
            Mail::raw($text, function ($message) use ($newMail){
                $message->to($newMail)->subject('メールアドレスの変更');
            });
            $send = 1;
        }

        $request->user()->save();

        return Redirect::route('profile.edit')->with('status', 'profile-updated')->with('send', $send??null);;
    }

    // ユーザーのメールアドレスを更新する
    public function mailUpdate(Request $request, $id, $token)
    {
        $usr = auth()->user();
        $duplicateCheck = user::where('email', $usr->new_email)->first();
        $timeLimitCheck = ($usr->updated_at->diffInHours(now()) < 1);

        //メールアドレス変更
        if($usr->id == $id 
            && $usr->new_email_token == $token
            && $usr->new_email
            && $usr->new_email_token
            && !$duplicateCheck
            && $timeLimitCheck
            ){
            $usr->email = $usr->new_email;
            $usr->new_email = null;
            $usr->new_email_token = null;
            $usr->save();
            $mailStatus = 'メールアドレスを変更しました。';

        //変更せず
        }else{
            $mailStatus = 'メールアドレスを変更できませんでした。';
        }

        return Redirect::route('mypage')->with('mailStatus', $mailStatus);
    }

```

```php:
//ランダムな英数字を出力
if (!function_exists('generateRandomString')) {
    function generateRandomString($length = 5) {
        $characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
        $randomString = '';
        for ($i = 0; $i < $length; $i++) {
            $randomString .= $characters[rand(0, strlen($characters) - 1)];
        }
        return $randomString;
    }
}
```

■メッセージ
```php: blade側
@if(session('mailStatus'))
    {{session('mailStatus')}}
@endif

//..

@if (session('send'))
    <p>※新しいメールアドレスに送られたURLをクリックして変更を完了させてください。</p>
@endif
```

■ルーティング
```php: route
Route::middleware(['auth:sanctum', 'verified'])
    ->get('/mypage/profile/mailupdate/{id}/{token}', [ProfileController::class, 'mailUpdate'])
    ->name('profile.mailUpdate');
```


もっとシンプルにできる方法がありましたら更新します。