ソフトデリート
このガイドに従うことで、モジュールとプラグインはコンポーネントにソフトデリートのサポートを追加できます。
すべてのエレメントタイプは、ソフトデリートをそのままサポートできます。 復元できるようにするための情報は、エレメントタイプを参照してください。
# データベーステーブルの準備
ソフトデリート可能なコンポーネントは、データベーステーブルに dateDeleted
カラムを持たなければなりません。 dateDeleted
値を持つ行は、ソフトデリートされたとみなされます。
// New table migration
$this->createTale('{{%tablename}}', [
// other columns...
'dateDeleted' => $this->dateTime()->null(),
]);
// Existing table migration
$this->addColumn('{{%tablename}}', 'dateDeleted',
$this->dateTime()->null()->after('dateUpdated'));
ソフトデリート可能なコンポーネントデータを含むテーブルは、(主キー以外に)固有の制約を適用するべきではありません。 もしそうしているなら、それらを削除する必要があります。
use craft\helpers\MigrationHelper;
// Stop enforcing unique handles at the database level
MigrationHelper::dropIndexIfExists('{{%tablename}}', ['handle'], true, $this);
$this->createIndex(null, '{{%tablename}}', ['handle'], false);
# 時間が経過したら、行を完全に削除
ソフトデリートされたテーブル行は、コンフィグ設定 softDeleteDuration にセットされた期間だけ保持され、その後完全に削除されるべきです。
すべてのリクエストごとに古い行をチェックするのではなく、Craft のガベージコレクションルーチンの一部にできます。
craft\services\Gc (opens new window) は、実行されるたびに run
イベントを発火します。 あなたのモジュール / プラグインの init()
メソッドから、それを利用できます。
use craft\services\Gc;
use yii\base\Event;
public function init()
{
paren::init();
Event::on(Gc::class, Gc::EVENT_RUN, function() {
Craft::$app->gc->hardDelete('{{%tablename}}');
}
}
hardDelete() (opens new window) メソッドは、dateDeleted
値にコンフィグ設定 softDeleteDuration よりも古いタイムスタンプがセットされたすべての行を削除します。
use craft\db\ActiveRecord; use craft\db\SoftDeleteTrait; class MyRecord extends ActiveRecord { use SoftDeleteTrait { behaviors as softDeleteBehaviors; } public function behaviors() { $behaviors = $this->softDeleteBehaviors(); $behaviors['myBehavior'] = MyBehavior::class; return $behaviors; } // ... :::
# Active Record クラスのアップデート
コンポーネントが対応する Active Record (opens new window) クラスを持つ場合、craft\db\SoftDeleteTrait (opens new window) をインポートすることによってソフトデリートサポートを追加できます。
use craft\db\ActiveRecord;
use craft\db\SoftDeleteTrait;
class MyRecord extends ActiveRecord
{
use SoftDeleteTrait;
// ...
}
トレイトは、次の特徴をクラスに付与するでしょう。
- find() (opens new window) はソフトデリートされていない(
dateDeleted
カラムがnull
である)行のみを返します。 - static な findWithTrashed() (opens new window) メソッドは、ソフトデリートされたかどうかに関わらず行を見つけるために追加されます。
- static な findTrashed() (opens new window) メソッドは、ソフトデリートされた(
dateDeleted
カラムがnull
ではない)行を見つけるために追加されます。 softDelete()
メソッドは、delete() (opens new window) の代わりに呼び出すために追加され、行を削除するのではなく行のdateDeleted
カラムを現在のタイムスタンプで更新します。restore()
メソッドは、dateDeleted
値を削除することによってソフトデリート行を復元するために追加されます。
内部的には、トレイトはビヘイビア (opens new window)として実装されている Yii 2 の ActiveRecord Soft Delete Extension (opens new window) を使用します。
クラスがすでに独自のビヘイビアを定義している場合、インポート時にトレイトの behaviors() (opens new window) メソッドをリネームし、あなたの behaviors()
メソッドから手動で呼び出す必要があります。
use craft\db\ActiveRecord;
use craft\db\SoftDeleteTrait;
class MyRecord extends ActiveRecord
{
use SoftDeleteTrait {
behaviors as softDeleteBehaviors;
}
public function behaviors()
{
$behaviors = $this->softDeleteBehaviors();
$behaviors['myBehavior'] = MyBehavior::class;
return $behaviors;
}
// ...
}
クラスが yii\db\ActiveRecord::find() (opens new window) を上書きしている場合、結果のクエリに dateDeleted
条件を追加する必要があります。
public static function find()
{
// @var MyActiveQuery $query
$query = Craft::createObject(MyActiveQuery::class, [static::class]);
$query->where(['dateDeleted' => null]);
return $query;
}
# その他のコードの更新
コンポーネントのテーブルを含む、データベースクエリのコードを確認してください。 それらも更新する必要があるでしょう。
テーブルからデータを選択するときは、
dateDeleted
値がある行を無視していることを確認してください。$results = (new \craft\db\Query()) ->select(['...']) ->from(['{{%tableName}}']) ->where(['dateDeleted' => null]) ->all();
Active Record クラスを使用してテーブルから行を削除する場合、delete() (opens new window) ではなく、新しい
softDelete()
メソッドを呼び出してください。$record->softDelete();
クエリコマンドを使用してテーブルから行を削除する場合、delete() (opens new window) ではなく、craft\db\Command::softDelete() (opens new window) を呼び出してください。
\Craft::$app->db->createCommand() ->softDelete('{{%tablename}}', ['id' => $id]) ->execute();
# ソフトデリートされた行の復元
ガベージコレクションによってまだ完全に削除されていない、ソフトデリートされた行を復元するには2つの方法があります。
Active Record クラスで
restore()
メソッドを呼び出す。$record = MyRecord::findTrashed() ->where(['id' => $id]) ->one(); $record->restore();
クエリコマンドで craft\db\Command::restore() (opens new window) を呼び出す。
\Craft::$app->db->createCommand() ->restore('{{%tablename}}', ['id' => $id]) ->execute();