こんにちは、編集長Kです。
アプリを作っていると必ず悩むのが「退会処理」です。
ユーザーが退会したら、関連データも全部消すの? 間違えて退会した人のために、少し猶予を持たせたいですよね。
今回は、そんな悩みを一発で解決するお話です。
Laravelとデータベースの強力な機能を組み合わせます。
この記事で解説する手順の全体像は以下の通りです。
- 論理削除と物理削除の仕組みを知る
- DBにCASCADE(連鎖削除)を設定する
- LaravelにPrunable(自動パージ)を設定する
- スケジュールを登録して自動化する
前提条件として、以下の環境を想定しています。
- Laravel 8以降(できれば11以降)の環境
- 基本的なマイグレーションの知識
手順①:論理削除と物理削除の違いを知る
まずはここからです。
退会処理には「論理削除」と「物理削除」の2段階があります。
【論理削除】は、データに「削除済み」という目印をつけるだけです。
Laravelなら deleted_at に日付が入ります。
画面上からは消えますが、実はDBの中にはしっかり残っています。
ユーザーが「やっぱり退会やめた!」と言った時、すぐ復旧できるというわけです。
一方、【物理削除】はDBから完全にデータを消し去ります。
DELETE文が走り、ハードディスクからもデータが消滅します。
個人情報保護の観点からも、最終的には物理削除が必要です。
今回は「退会時は論理削除し、30日後に自動で物理削除する」仕組みを作ります。
手順②:DBにCASCADEを設定する
物理削除されたとき、関連データも一緒に消したいですよね。
例えばユーザーが消えたら、その人の設定データも消す。
これにはDBの【ON DELETE CASCADE】を使います。
まずは、下記を実行してマイグレーションを作成してください。
Schema::create('user_settings', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')
->constrained('users')
->cascadeOnDelete(); // 親が消えたら子も消す設定
$table->timestamps();
});これで、親が消えれば子も自動で消えるようになります。 DB側が勝手にやってくれるので安心ですね。 これでOKです。
手順③:LaravelにPrunableを設定する
次はLaravel側の設定です。 30日経った論理削除データを探して、物理削除します。
これには【Prunable】という機能を使います。
続いて、下記です。Userモデルに追記してください。
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Prunable;
class User extends Authenticatable
{
use SoftDeletes, Prunable;
// 古い論理削除データを集める条件を書きます
public function prunable()
{
return static::onlyTrashed()
->where('deleted_at', '<=', now()->subDays(30));
}
}これで「30日前の論理削除データ」を消す準備ができました。
コードがとてもすっきりしていますね。 これでOKです。
手順④:スケジュールを登録して自動化する
最後に、このお掃除処理を毎日自動で動かします。
Laravel 11なら routes/console.php に書くだけです。
続いて、下記を実行してください。
use Illuminate\Support\Facades\Schedule;
// 毎日深夜にPrunableを実行してお掃除する
Schedule::command('model:prune')->daily();これでLaravel側の準備は完了です。
しかし、これだけでは自動で動きません。
サーバー側で「定期的にLaravelを動かす」設定が必要です。
これが【Cron(クーロン)設定】です。
Linuxサーバーならターミナルで crontab -e コマンドを叩きます。
そして、以下の1行を追加してください。
* * * * * cd /あなたのプロジェクトのパス && php artisan schedule:run >> /dev/null 2>&1これで、サーバーが1分ごとにLaravelの時計をチェックしてくれます。
そして、深夜になると先ほどの model:prune が実行される仕組みです。
忘れがちな設定ですが、これで本当の完全自動化です。 これでOKです。
よくあるエラーと解決策
「子テーブルのデータが全然消えない!」 現場で本当によくある落とし穴です。
原因は、子テーブルにもSoftDeletesをつけていること。
CASCADEは「物理削除」のときにしか発動しません。 子テーブルの論理削除をLaravel側で連鎖させるのは大変です。
解決策は【子テーブルにはSoftDeletesをつけない】こと。
親が見えなくなれば、アプリ上は子テーブルも見えなくなります。
そして30日後、DB側で一気に物理削除させましょう。
これが一番シンプルでバグのない設計です。
まとめ
ここまでお疲れ様でした。
退会処理のベストプラクティスが伝わりましたか?
この設計なら、ユーザーは間違えてもアカウントを復帰できます。
運営側も無駄なデータが溜まらず、管理がラクになります。
まさに一石二鳥というわけです。
この記事が参考になったら、ぜひX(旧Twitter)でシェアをお願いします!
編集長Kのアカウントのフォローも待ってますね。
それでは、また次回の記事でお会いしましょう!

コメント