Laravel でソフトデリートを実装する方法

こんにちはー!むちょこです。

この記事では、 Laravel でソフトデリート(論理削除)を実装する方法を丁寧めにご紹介します🙌

具体例があった方がわかりやすいと思いますので、 ここでは Flight モデル(テーブルは flights )のソフトデリート機能を実装していきます。他のモデルの場合も同様に実装してください。

また、Laravel のバージョンは 5.0 ~ 8.x を対象としています。

ソフトデリートとは

ソフトデリート(論理削除)とは、データを残したまま消したことにする削除方法です。

対義語として、ハードデリート(物理削除)というものがあります。こちらはデータを完全に削除します。

あとで復元させたくなりそうなデータは利便性を優先してソフトデリート

復元の必要はないデータはDBを最適化できるようにハードデリート

という風に使い分けたりします。

マイグレーション

まずはソフトデリートが使えるようDBの準備をしていきましょう!

artisan コマンドを使ってマイグレーションファイルを生成します。

コマンド
$ php artisan make:migration add_deleted_at_to_flights --table=flights

Laravel にはソフトデリート用のスキーマビルダが予め用意されていますので、それをマイグレーションファイルの up() メソッドに書きます。

/database/migrations/xxxx_add_deleted_at_to_flights_table.php
    public function up()
    {
        Schema::table('flights', function (Blueprint $table) {
            $table->softDeletes();
        });
    }

これを実行すると、指定のテーブルに NULL 可の deleted_at カラムが追加されます。

down() メソッドにも巻き戻し用の処理を忘れずに書いておきましょう。

Laravel 5.8 以降とそれより前では書き方が違うので注意してください。

Laravel 5.8 以降

Laravel 5.8 以降は、 $table->dropSoftDeletes() を使って中身を気にすることなく実装することができます。

/database/migrations/xxxx_add_deleted_at_to_flights_table.php
    public function down()
    {
        Schema::table('flights', function (Blueprint $table) {
            $table->dropSoftDeletes();
        });
    }

Laravel 5.7 以前

Laravel 5.7 以前には専用のスキーマビルダがありませんので、 deleted_at カラムを明示して削除します。

/database/migrations/xxxx_add_deleted_at_to_flights_table.php
    public function down()
    {
        Schema::table('flights', function (Blueprint $table) {
            $table->dropColumn('deleted_at');
        });
    }

あとはマイグレートを実行して反映させたら、DB側の準備は完了です。

コマンド
php artisan migrate
参考( Laravel 6.x の場合)

https://readouble.com/laravel/6.x/ja/migrations.html

モデル

次はモデルクラスの準備です。

Laravel にはソフトデリート用の SoftDeletes トレイトがありますので、それを使います。

これも Laravel 5.8 以降とそれより前で書き方が違いますので、注意が必要です。また、 Laravel 8.x や自分でカスタマイズしている方はディレクトリも異なりますので各自の環境に合わせてファイルを探してください。

Laravel 5.8 以降

Laravel 5.8 以降では SoftDeletes トレイトを追加するだけで OK です。

app/Flight.php
use Illuminate\Database\Eloquent\SoftDeletes;

class Flight extends Model
{
    use SoftDeletes;
}

Laravel 5.7 以前

Laravel 5.7 以前では、SoftDeletes トレイトの追加と $date プロパティへ deleted_at の追加を行います。

app/Flight.php
use Illuminate\Database\Eloquent\SoftDeletes;

class Flight extends Model
{
    use SoftDeletes;

    /**
     * 日付へキャストする属性
     *
     * @var array
     */
    protected $dates = ['deleted_at'];
}

これでモデルクラスの準備も完了です!

コントローラ等

最後に、コントローラ等から使う方法をご紹介します。

モデルをソフトデリートする

前述のように DB とモデルクラスの準備ができていれば、いつも通りモデルに対して delete() メソッドを実行することでソフトデリートされます。

app/Http/Controllers/SampleController.php
App\Flight::find($id)->delete();

ソフトデリート済みモデルも含めた結果を得る

ソフトデリートされたモデルは基本的にないものとして扱われ、クエリの結果からも除外されます。

もしソフトデリート済みのモデルも取得したい場合は、以下のように withTrashed() を使います。

app/Http/Controllers/SampleController.php
$flights = App\Flight::withTrashed()
                ->where('account_id', 1)
                ->get();

モデルがソフトデリート済みか確認する

trashed() メソッドの返り値が true なら削除済み、 false なら削除されていないことが確認できます。

app/Http/Controllers/SampleController.php
if ($flight->trashed()) {
    // 削除済み
}

ソフトデリートを解除する

一度ソフトデリートしたモデルを削除されていない状態に復元したい場合は、 restore() メソッドを使います。

app/Http/Controllers/SampleController.php
$flight->restore();

よく使うメソッドはこんな感じです。もっと知りたい方はこちらをご覧ください✨

https://readouble.com/laravel/6.x/ja/eloquent.html