【Laravel】Eloquentのソフトデリート機能で論理削除を実装する

こんにちは。今回はEloquentのソフトデリート機能について説明します。

ソフトデリートとは

ソフトデリートとはデータ削除処理を実行した際に、データを物理的に削除せずに、削除扱いにする機能のことです。一言で説明するのは難しいので、普段皆さんが使用している機能で例えます。

OSのゴミ箱機能がソフトデリートの機能そのものです。ゴミ箱に入れたデータは削除扱いになりますが、実際にファイルが消えている訳ではありません。復元しようと思えばゴミ箱から出して、ファイルを復元することもできます。

一時的に削除扱いにしたいのですが、復元する可能性もあるのでデータは残しておきたい時にソフトデリートは役に立ちます。例えば以下のようなケースです。

  • ユーザーを一時的に無効にしてシステムへのアクセスを制限したい時
  • 重要なデータを誤って削除してしまった時に保険として復元機能を用意しておきたい時

EloquentのSoftDeletes機能を利用することで簡単にソフトデリートの機能を実装することができます。今回はLaravelのUsersテーブルにソフトデリート機能を組み込む手順を解説していきたいと思います。

deleted_atカラムをテーブルに追加する

Laravelではテーブルのdeleted_atカラム(削除日時)に値が入っている場合は、データは削除されたとみなしますので、deleted_atカラムを追加する必要があります。新たにマイグレーションを作成しましょう。

$ php artisan make:migration add_softdelete_to_users
Created Migration: 2021_07_31_045724_add_softdelete_to_users

$table->softDeletes()メソッドでdeleted_atカラムを作成することができます。

public function up()
    {
        Schema::table('user', function (Blueprint $table) {
            $table->softDeletes();
        });
    }

マイグレーションを実行します。usersテーブルにdeleted_atカラムが作成されます。

$php artisan migrate

Migrating: 2021_07_31_045724_add_softdelete_to_users
Migrated:  2021_07_31_045724_add_softdelete_to_users (3.75ms)

EloquentモデルにSoftDeletes機能を組み込む

UserモデルにIllumimate\Database\Eloquent\SoftDeletesトレイトを組み込みます。こうすることでdeleteメソッドでモデルを削除した際に、ソフトデリートされます。

use Illuminate\Database\Eloquent\SoftDeletes;

class User extends Model
{
    use SoftDeletes;
}

ソフトデリートを試す

実際にソフトデリートを実行してみましょう。tinkerを使用してモデルの操作を行います。今回使用するusersテーブルに登録されているデータは以下です。

idnameemaildeleted_at
1joejoe@xxx.xxx.xxx
2bobbob@yyy.yyy.yyy
usersテーブルのサンプルデータ

id=1のデータをdeleteメソッドで削除します。

>>> App\Models\User::find(1)->delete();
=> true

ソフトデリートしたデータは通常のクエリで取得されなくなります。allメソッドでuserモデルを全て取得してみます。id=1のデータが取得されないことがわかります。

>>> App\Models\User::all();
=> Illuminate\Database\Eloquent\Collection {#4344
     all: [
       App\Models\User {#4354
         id: "2",
         name: "bob",
         email: "bob@yyy.yyy",
         deleted_at: null,
       },
     ],
   }

削除済のデータも取得する場合は、withTrashedメソッドを使用します。id=1のデータも取得することができました。id=1のデータはソフトデリートされているのでdeleted_atにタイムスタンプが登録されていることがわかります。

>>> App\Models\User::withTrashed()->get();
=> Illuminate\Database\Eloquent\Collection {#4357
     all: [
       App\Models\User {#4358
         id: "1",
         name: "joe",
         email: "joe@xxx.xxx",
         deleted_at: "2021-07-31 05:12:05",
       },
       App\Models\User {#4359
         id: "2",
         name: "bob",
         email: "bob@yyy.yyy",
         deleted_at: null,
       },
     ],
   }

ソフトデリートされたデータのみ抽出するにはonlyTrashedメソッドを使用します。

>>> App\Models\User::onlyTrashed()->get();
=> Illuminate\Database\Eloquent\Collection {#4347
     all: [
       App\Models\User {#4356
         id: "1",
         name: "joe",
         email: "joe@xxx.xxx",
         updated_at: "2021-07-31 05:12:05",
         deleted_at: "2021-07-31 05:12:05",
       },
     ],
   }

ソフトデリートを復元するにはwithTrashedメソッドとrestoreメソッドを使用します。

>>> App\Models\User::withTrashed()->restore();
=> 2

再びallメソッドを実行してみると、復元したid=1のデータも取得できました。deleted_atにはnullが設定されているので、復元できたことがわかります。

>>> App\Models\User::all();
=> Illuminate\Database\Eloquent\Collection {#4360
     all: [
       App\Models\User {#4361
         id: "1",
         name: "joe",
         email: "joe@xxx.xxx",
         deleted_at: null,
       },
       App\Models\User {#4362
         id: "2",
         name: "bob",
         email: "bob@yyy.yyy",
         deleted_at: null,
       },
     ],
   }

Laravel

Posted by kobainmac