Laravelで論理削除からの復元処理を実装した時の備忘録

2021.04.14

見出し画像

前回実装した論理削除の今回は復元処理について書いていきます。こう考えるとユーザーにとっては論理削除の方が優しいですね。

前提

前回の記事の内容を把握している。

やること

確認メールを使ったアカウント復元処理

大まかな流れ

ルーティング記載追加

ビュー記載追加

コントローラー記載追加

確認メール作成

モデル記載追加

って感じの流れで行きます。

ルーティング記載追加

3つのアクションを用意します。

1 Route::get('/user/restore', 'UserController@restore_user')->name('restore_user');
2 Route::post('/user/restore', 'UserController@restore_user_send')->name('restore_user_send');
3 Route::get('/user/restore/{user}', 'UserController@restore_user_confirm')->name('restore_user_confirm');

1,  復元申請ページです。emailを使って実装します。

2,  emailが条件に一致した場合は、確認メールを送信する処理です。

3,  確認メールをクリックした時の処理が記載してあります。

退会申請ページへのリンク

ページのどこかに記載しておけば大丈夫ですね。

@if (Route::has('restore_user'))
   <a class="btn btn-link" href="{{ route('restore_user') }}">
       {{ __('退会処理を取り消したい方') }}
   </a>
@endif

ビュー記載追加

申請ページのビューです。

@if(session('say')) 
 <div class="alert alert-success" role="alert">
   {{ session('say') }}
 </div>
@endif

<form method="POST" action="{{ route('restore_user_send') }}">
 @csrf

 <div class="form-group row">
     <label for="email" class="col-md-4 col-form-label text-md-right">{{ __('以前使用していたE-Mail') }}</label>
   <input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus>
 </div>
 <button type="submit" class="btn btn-primary">
    {{ __('申請する') }}
 </button>
</form>

最小限しか書いていません。上部のセッション部分についてはユーザーが見つからなかった時の表示です。

emailをコントローラーに送信するようにしています。

モデル記載追加

通知ファイルの読み込みです。後から作成する通知クラスをuserから呼び出せるように設定しています。

Userモデル

use \App\Notifications\UserRestore;

......省略

public function sendUserRestoreNotification($user_id)
{
   $this->notify(new UserRestore($user_id));
}

引数が渡されているので、呼び出し時に引数がいるということに注意してください。

コントローラー記載追加

こちらもルーティングと同じく3つのアクションから成り立っています。

use Carbon\Carbon;

public function restore_user() 
{
   return view('users.restore_user');
}

public function restore_user_send(Rrequest $request)
{
1  $check_user = User::withTrashed()->where(['email' => $request->email])->first();
2  if(isset($check_user->deleted_at)) {
       $check_user->deleted_at = null;
       $check_user->email_verified_at = null;
3      $check_user->save();
4      Auth::logout();
5      $check_user->sendUserRestoreNotification($check_user->id);
       return redirect()->route('home')->with('say', '確認メールをお送りしたので、承諾してログインを完了しましょう');
   } else {
       return redirect()->back()->with('say', '条件に一致するユーザーを取得できませんでした');
   }
}

public function restore_user_confirm(User $user)
{
6  if($user->email_verified_at == null) {
       $now_time = Carbon::now('Asia/Tokyo');
       $user->email_verified_at = $now_time;
7      $user->save();
       Auth::login($user);
8      return redirect()->route('my_page', ['user' => $user->id])->with(['user' => $user, 'say' => 'アカウントの復元が完了しました']);
   } else {
       return redirect()->route('home')->with('say', '何らかの理由で、復元が出来ませんでした。もう一度お試しください');
   }
}

確認メール送信まで

1,  送信されたemailと同じユーザーがいるかどうかを、withTrashed()メソッドで論理削除したユーザーも含めて検索を掛けます。

2,  取得したユーザーが論理削除されたユーザーである事を確認します。

3,  deleted_atとemail_verified_atカラムを削除して保存します。復元への手順で、確認メールが正しく動くようにです。

4,  ログアウトさせます。そのままだとリダイレクトログインしてしまうので、確認メールの意味がなくなってしまいます。

5,  先ほどモデルに設定した確認メール通知用メソッドを発火させます。

確認メールをクリックした後

6,  そのユーザーはまだemail認証されていない事を確認します。

7,  ユーザーのemail認証カラムを保存してからログインさせます。

8,  ユーザー詳細ページにリダイレクトで飛ばす。

確認メール作成

コマンドでファイルを作成し、ファイルに記載を加えていきます。

php artisan make:notification UserRestore
<?php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Facades\Lang;

class UserRestore extends Notification
{
   use Queueable;
1  public $user_id;    
   /**
    * Create a new notification instance.
    *
    * @return void
    */
2  public function __construct($user_id)
   {
       $this->user_id = $user_id;
   }

   /**
    * Get the notification's delivery channels.
    *
    * @param  mixed  $notifiable
    * @return array
    */
   public function via($notifiable)
   {
       return ['mail'];
   }

   /**
    * Get the mail representation of the notification.
    *
    * @param  mixed  $notifiable
    * @return \Illuminate\Notifications\Messages\MailMessage
    */
   public function toMail($notifiable)
   {
3      return (new MailMessage)
       ->subject(Lang::get('ユーザー復元認証メールです'))
       ->line(Lang::get('下記リンクをクリックして復元認証を完了してください'))
       ->action(Lang::get('復元認証メール'), url('user/restore',$this->user_id))
       ->line(Lang::get('この変更に身に覚えがない場合は、無視してください'));
   }
     。。。。省略
}

1,  $user_idをこのファイルで使用出来る事を明示します。

2,  初期値として渡された引数の値を代入します。

3,  実際のメール文の部分です。actionの部分にuser_idを使用してクリックした先のアクションを指定しています。

ここまで出来ればユーザーはマイページに飛んで復元される形になると思います。

まとめ

通知クラスの設定、アクションの定義などが出来ていればある程度出来ると思います。万が一を考えると論理削除の方が良いかもですね。

emailのバリデーションやtestなども追加で実装出来ると良いですね!

最近はVue.jsのテストで苦しんでいますwwただこれ出来るようになったら良いな〜って思いもあるのでやったりますw

今回はそんな感じで!!

以上!

参考にしたサイト