1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

laravelで視覚的に理解する論理削除

Last updated at Posted at 2021-05-01

論理削除とは?

論理削除とは実際にはデータを削除せず、見かけ上削除しているように見える技術である。
データベースにはデータが残っているので、必要な時にそのレコードを復元したり、一部の権限の人にはレコードを公開したりできる。
例えば、管理者はそのレコードを確認できるがユーザーはその内容を確認できないように設定することができる。
パソコンの不要ファイルを削除してゴミ箱に格納するイメージに近い。

Laravlではマイグレーションファイルとモデルへの設定で論理削除用のカラムを設定できるので視覚的に検証してみることにした。

マイグレーションファイルの準備

今回はpeopleテーブルをもとに論理削除する。
論理削除をする上で対応するpeopleテーブルに対応するモデルも必要となる。
Person.phpは以下のようにする。

Person.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class Person extends Model
{
    use SoftDeletes;
    use HasFactory;
}

まずはrunメソッドを以下のように編集してマイグレーションする。

xxx_create_people_table
public function up()
    {
        Schema::create('people', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->integer('age');
            $table->timestamp('created_at')->useCurrent()->nullable();
            $table->timestamp('updated_at')->useCurrent()->nullable();
            $table->softDeletes();
        });
    }

また、ダミーデータも挿入するとテーブルの中身は以下のようになる。
スクリーンショット 2021-05-01 17.08.29.png

コントローラーの作成

今回はSoftDeleteControllerという名前で作成する。

コントロローラーは以下のように記述します。

SoftDeleteController
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Person;
class SoftDeleteController extends Controller
{
    public function index()
    {
        $people = Person::all(); // softdeletesカラムがnullの物を取得
        $deleted = Person::onlyTrashed()->get(); // 論理削除済のデータ取得
        $param = ['people' => $people,'deleted' => $deleted];
        return view('delete', $param);
    }
    
 
    /*
     * 論理削除
     */
    public function delete($id)
    {
        Person::find($id)->delete(); // softDelete
 
        return redirect()->to('delete');
    }
    public function restore($id)
    {
        Person::onlyTrashed()->find($id)->restore(); // restoreメソッドで復元
 
        return redirect()->to('delelte');
    }
 
    /*
     * force delete Person
     */
    public function forceDelete($id)
    {
        Person::onlyTrashed()->find($id)->forceDelete(); //forceDeleteメソッドで物理削除
 
        return redirect()->to('delete');
    }
}

論理削除されたレコードの取得

indexアクションの
Person::onlyTrashed()->get(); のように
モデル名::onlyTrashed()->get(); で論理削除されたレコードを取得できる。

論理削除

deleteアクションの
Person::find($id)->delete();のように
モデル名::find(対象のレコード)->delete(); で論理削除が実行できる。

論理削除されたレコードの復元

restoreアクションの
Person::onlyTrashed()->find($id)->restore();のように
モデル名::onlyTrashed()->find(対象のレコード)->restore(); で対象の論理削除されたレコードを復元ができる。

論理削除したレコードの完全削除

forcedeleteアクションの
Person::onlyTrashed()->find($id)->forceDelete(); で対象の論理削除されたレコードを完全削除(物理削除)できる

ビューページ

ビューページとしてdeleteディレクトリを作成し、index.phpを作成する。

index.php
<style>
   th {
      background-color: black;
      color: white;
      padding: 5px 30px;
    }
    td {
      border: 1px solid black;
      padding: 5px 30px;
      text-align: center;
    }
</style>
<body>
  <a href="/delete/create">メンバー追加</a>
  <h2>未削除</h2>
  <table>
        <tr>
            <th>ID</th>
            <th>名前</th>
            <th>削除ボタン</th>
        </tr>
        @forelse ($people as $person)
            <tr>
                <td>{{ $person->id }}</td>
                <td>{{ $person->name }}</td>
                <td>
                    <a href="/delete/delete/{{ $person->id}}">削除</a>
                </td>
            </tr>
        @empty
            <tr>
                <td>-</td>
                <td>-</td>
                <td>-</td>
            </tr>
        @endforelse
  </table>
  <h2>削除済</h2>
  <table>
          @forelse ($deleted as $delete)
              <tr>
                  <td>{{ $delete->id }}</td>
                  <td>{{ $delete->name }}</td>
                  <td>
                      <a href="/delete/restore/{{ $delete->id}}">復旧</a>
                      <a href="/delete/force-delete/{{ $delete->id}}">完全削除</a>
                  </td>
              </tr>
          @empty
              <tr>
                  <td>-</td>
                  <td>-</td>
                  <td>-</td>
              </tr>
          @endforelse
  </table>
</body>

ルーティングを設定してこのdelete/index.blade.phpにアクセスすると以下のようになる。

スクリーンショット 2021-05-01 18.41.53.png

ルーティングも設定する。

web.php
Route::group(['prefix' => 'delete'], function () {
    Route::get('', [SoftDeleteController::class,'index'])->name('delete');// 一覧表示
    Route::get('delete/{id}', [SoftDeleteController::class,'delete']); // 論理削除
    Route::get('restore/{id}', [SoftDeleteController::class,'restore']); // 復元
    Route::get('force-delete/{id}', [SoftDeleteController::class,'forceDelete']); // 完全削除
});

実際にdeleteにアクセスして削除ボタンを押して、論理削除してみる。
画面は下記のようになる。
スクリーンショット 2021-05-01 18.51.04.png
また、テーブルには削除された時刻が表示される。
スクリーンショット 2021-05-01 18.53.02.png

削除済のレコードの復旧ボタンを押して、復元するとそのレコードは未削除の欄に戻り、テーブルの削除された時間もNULLになる。
また、完全削除ボタンを押すとテーブルからレコードが削除されて、ブラウザからも存在がなくなる。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?