Laravelの多対多のリレーションで、中間テーブルに論理削除を実装する。
テーブル準備
マイグレーションファイル作成
php artisan make:migration create_article_tag_table
deleted_at
カラムを追加する
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateArticleTagTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('article_tag', function (Blueprint $table) {
$table->integer('article_id');
$table->integer('tag_id');
$table->timestamp('deleted_at')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('article_tag');
}
}
中間テーブルの更新
updateExistingPivot
を使用して中間テーブルを更新。
use Carbon\Carbon;
public function delete(Request $request, Article $article)
{
$ids = $article->tags->pluck('id');
$article->tags()->updateExistingPivot($ids, ['deleted_at' => Carbon::now()]);
return redirect('/articles');
}
論理削除以外のレコードを取得
whereNull
メソッドでdeleted_at
を使用すると、論理削除以外のレコードが取得できます。
use App\Models\Tag;
class Article extends Model
{
public function tags()
{
return $this
->belongsToMany(Tag::class)
->whereNull('deleted_at')
->withTimestamps();
}
}
中間テーブルで論理削除するべきか
中間テーブルで論理削除をするのなら、そもそもテーブル設計を見直す必要がありそうです。
注意: ピボットモデルでは、SoftDeletesトレイトを使わないほうが良いでしょう。ピボットレコードのソフト削除が必要な場合は、ピボットモデルを実際のEloquentモデルに変換することを考えてください。
「とりあえず削除フラグ」はSQLアンチパターンです。