Laravel には論理削除(ソフトデリート)の機能がついています。
Eloquent ORM を使うことで、デフォルトの認証機能から少しの追加で論理削除を導入することができます。
(※DBファサードではできない)
Laravel の機能を使って論理削除を実装するのもよし、削除フラグを使って自力で論理削除を実装するのもよし。
しかし、せっかく Laravel を使っているのなら Laravel の論理削除を使うほうがいいですよね。
今回はこの論理削除についてエントリーします。
またLaravel 5.7 以前と 5.8 以降ではやり方が若干異なるため、そのあたりも記載しようと思います。
データベースからデータそのものを物理的に削除するのではなく、そのレコードに対して削除の操作がなされた時刻のタイムスタンプを保持し、それをフラグのように扱うことで見かけ上削除されたような挙動をさせることをいいます。
前提条件
Laravel の認証機能(Auth)を作成しており、 Users テーブルがあるものとします。
この Users テーブルに論理削除のカラムを追加するところからはじめます。
手順
マイグレーションファイルの作成
まず Users テーブルに論理削除用のカラムを追加するためのマイグレーションファイルを作成します。
$ php artisan make:migration add_softDeletes_users_table –-table=users
実演
マイグレーションファイルの作成についてわからない方は以下をご参照ください。
マイグレーションファイルの記述
up() と down() にそれぞれカラムの追加と削除のコードを記述します。
:
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->softDeletes();
});
}
:
public function down()
{
Schema::table('users', function (Blueprint $table) {
// 5.8 以降は専用のスキーマビルダが用意されている
$table->dropSoftDeletes();
// 5.7 以前は以下のように記述
$table->dropColumn('deleted_at');
});
}
マイグレーションの実行
あとはマイグレートを実行して反映させたら、DB側の準備は完了です。
php artisan migrate
実演
この時点で DB のテーブル構成を確認してみると deleted_at カラムが追加されているのがわかるかと思います。
モデル(User.php)への記述
プロジェクトを作成した時点でUserモデルはできているかと思います。
ここでの記述は
1)Soft Deletesトレイトのuse
2)メンバ変数 $dates に deleted_at を追加
を付け加えます。
:
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Database\Eloquent\SoftDeletes; // トレイトを使う
class User extends Authenticatable
{
//SoftDeletesトレイトをuse
use SoftDeletes;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name', 'email', 'password','department','plane_pass','deleted_at'
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
//メンバ変数 $dates に deleted_at をセットする
protected $dates = ['deleted_at'];
}
実演
SoftDeletes トレイトを追加するだけでOKです。
:
use Illuminate\Database\Eloquent\SoftDeletes;
class Flight extends Model
{
use SoftDeletes;
:
}
:
コントローラ(UsersController.php)への記述
削除ボタンを押すと以下のメソッドが実行されるように記述していきましょう。
ここでのポイントは、DBファサードではなく、Eloquent ORM にて delete() メソッドを実行するということです。
find() メソッドに削除対象IDを渡して、インスタンスを取得し、delete() メソッドを実行する事で deleted_at カラムにタイムスタンプが挿入され、論理削除が行われます。
※ちなみに、DBファサードで delete() メソッドを実行すると、通常の物理削除になります。
:
/**
* アカウント削除
*/
public function accountDelete($id)
{
//削除対象レコードを検索
$user = \App\User::find($id);
//削除
$user->delete();
//リダイレクト
return redirect()->to('account_list')->with('flash_msg','削除が完了いたしました。');
}
:
この辺りの説明は以下のページに詳しく説明しています。
動作確認
実際に動作確認をしてみましょう。
一覧リストからはレコードが非表示なっているのが確認できるかと思います。
どうしてもDBファサードでユーザー一覧を取得したい場合は、単純に Where 句を付ければ論理削除の形になります。
/**
* ユーザ一覧を返却する
* @return mixed
*/
public function getUsers()
{
$users = DB::table($this->table)
->whereNull('deleted_at')
->get();
return $users;
}
また DB を見ると以下のように deleted_at カラムにタイムスタンプが記載されているのがわかります。
物理削除に変更してみる
基本的には論理削除で運用しますが、データ整理などで物理削除も必要になる場合もあります。
その場合、forceDelete() メソッドを用いる事で、論理削除ではなく、物理削除を行う事ができます。
/**
* アカウント削除
*/
public function accountDelete($id)
{
//論理削除
//$user = \App\User::find($id);
//$user->delete();
//物理削除
$user = \App\User::withTrashed()->where('id',$id)->forceDelete();
//リダイレクト
return redirect()->to('account_list')->with('flash_msg','削除が完了いたしました。');
}
以上です。
仕事で Laravel を使っています。気づいたことや新しい発見など情報を発信していきます。問い合わせはこちら。