章: 第2章: データベース応用
DELETE FROM posts WHERE id = 1 —— 本当に消してしまっていいですか?
ユーザーが投稿を削除したあと、「やっぱり復元したい」と言われたら?法的な理由でデータを保持しなければならない場合は?物理削除(レコードの完全消去)は取り返しがつきません。
論理削除(ソフトデリート)は deleted_at というタイムスタンプを使って「削除済み」フラグを立てるだけで、レコード自体はDBに残り続けます。
ソフトデリートの実装
<?php
use Illuminate\Database\Eloquent\SoftDeletes;
class Post extends Model {
use SoftDeletes;
}
// 削除(deleted_atに日時が入る)
Post::find(1)->delete();
// 削除済みを含めて取得
Post::withTrashed()->get();
// 復元
Post::withTrashed()->find(1)->restore();
物理削除 vs 論理削除
| 観点 | 物理削除(DELETE) | 論理削除(ソフトデリート) |
| データの復元 | 不可能 | restore() で復元できる |
| 監査ログ | 記録が消える | deleted_at で削除日時が残る |
| 通常の取得 | 削除済みは取得されない | 同じ(deleted_at IS NULLで絞られる) |
| DBの肥大化 | 起きない | 削除データが蓄積する |
チェックポイント:
SoftDeletesトレイトを使うと、Post::all()は自動的にdeleted_at IS NULLの条件が付きます。削除済みを取得したいときは明示的にwithTrashed()が必要です。
マイグレーションでの設定
<?php
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('body');
$table->timestamps();
$table->softDeletes(); // deleted_at カラムを追加
});
完全削除が必要なとき
<?php
// 論理削除(通常の削除)
$post->delete();
// 物理削除(本当に消す)
$post->forceDelete();
チェックポイント: GDPRなどの規制対応で「ユーザーのデータを完全削除する」必要があるときは
forceDelete()を使いますが、通常はソフトデリートを優先しましょう。
まとめ & 次のステップ
- 論理削除はレコードを消さずに
deleted_atタイムスタンプで「削除済み」を表現する SoftDeletesトレイトで通常のクエリは自動的に削除済みを除外する- 復元・監査・規制対応など、データを保持する理由は実務で頻出する
次回から第3章: RESTful API設計に入ります。まずREST設計の基本として、リソースとHTTPメソッドを使ったAPI設計の原則を学びます。