1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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

Last updated at Posted at 2024-02-02

やりたいこと

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

smtpサーバーの準備

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

userコントローラー編集

app/Controllers/user.php

+ use Illuminate\Contracts\Auth\MustVerifyEmail;

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

authをverifiedに変える

routes/web.php
middleware('auth')-> //メール認証前でも通す
middleware('verified')-> //メール認証前は通さない

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

問題

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

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

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

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');
        });
    }
};

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

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);
    }

//ランダムな英数字を出力
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;
    }
}

■メッセージ

blade側
@if(session('mailStatus'))
    {{session('mailStatus')}}
@endif

//..

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

■ルーティング

route
Route::middleware(['auth:sanctum', 'verified'])
    ->get('/mypage/profile/mailupdate/{id}/{token}', [ProfileController::class, 'mailUpdate'])
    ->name('profile.mailUpdate');

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

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?