12

カスケード削除とsoftDeletesで外部キーを使用しようとしましたが、あまり運がありませんでした。

ユーザー、イベントの 2 つのテーブルがあります。両方のテーブルに softDeletes があります。

ユーザーは 0..n 個のイベントを持つことができます。
イベントには、次のようにユーザーの外部キーとして使用される user_id があります。

$table->foreign('user_id')->references('id')->on('users')->onDelete('CASCADE')->onUpdate('CASCADE');

問題は、ユーザーを削除すると論理的に削除されますが、そのイベントは削除されません-論理的な削除または物理的な削除のいずれかです。

私は何か間違ったことをしていますか、それともこれは正しい Eloquent の動作ですか?

次に、それが正しい動作である場合、削除カスケードを最適に実装するにはどうすればよいですか? たぶん、このように私のモデルで delete() メソッドをオーバーライドしています...

public function delete()
{
  //delete all events...
  __parent::delete()
}

?

4

3 に答える 3

11

問題の主キーを変更していないため、DB の外部キーは何もしません。主キーを更新または削除した場合にのみ、関連する行が変更されます。

このトピックについて私が見つけたすべての解決策は、Eloquent のモデル イベントを使用して削除イベントをリッスンし、関連するテーブルを更新することです。

これについての StackOverflow の質問が 1 つあります。

または、メソッドを「拡張」してdelete()、機能を直接含めることもできます。これが例です。

于 2013-07-31T21:11:14.570 に答える
2

あなたはこれを考えすぎています。

ユーザーを削除する直前にイベントを削除します。

$user->events()->delete();
$user->delete();

または、ユーザー モデルで顧客削除関数を作成します。

public function customDelete(){
    $this->events()->delete();
    return $this->delete();
}

モデル オブザーバーを追加して、deleting または delete イベントを監視することもできますが、上記のシナリオでは、前の 2 つの方法がより単純なソリューションになります。

http://laravel.com/docs/4.2/eloquent#model-observers

于 2015-01-22T17:49:50.227 に答える
0

私の理解が正しければ、両方のテーブルでソフト削除をカスケードしようとしていますか?

ON UPDATE CASCADE でこれを行うのは正しいアプローチではないと思います。その理由を説明しようと思います...

これを行うには、外部キーと複合キーの関係を作成する必要があります。

つまり、(events.user_id と deleted_at) を (user.id と delete_at) にリンクする必要があります。一方を変更すると、他方が更新されます。

null 値にリンクすることはできないため、まず、deleted_at 列にデフォルトのルールを追加する必要があります。

したがって、両方のテーブルの移行に追加してください... $table->softDeletes()->default('0000-00-00 00:00:00');

「id」と「deleted_at」を使用して一意のキーをユーザー テーブルに追加します。

Schema::table('users; function($table) { $table->unique(array('id','deleted_at')) });

次に、イベントテーブルでそのように外部キーを作成します(一意のキーへのリンク)

Schema::table('events; function($table) { $table->foreign(array('user_id','deleted_at'),'events_deleted_at_foreign_key')-> }->references(array('id','deleted_at'))->on('users')->onUpdate('CASCADE'));

これを実行すると、ユーザーをソフト削除すると、イベントがソフト削除されることがわかります。

ただし、ここでイベントをソフト削除しようとすると、外部キーの制限で失敗します。なぜあなたは尋ねるかもしれません!?

あなたがしているのは、両方のテーブルで id,deleted_at を使用して親子関係を作成することです。親を更新すると、子が更新されます。そして、その関係は途切れることはありません。ただし、子を更新すると、関係が壊れて、子がテーブルに孤立したままになります。これは、外部キーの制限に失敗します。

すっごく長い答えですが、うまくいけば、あなたがやろうとしていることがうまくいかない理由の良い説明があり、ON UPDATE CASCADE でこれをやろうとしている時間を大幅に節約できます. TRIGGERS に入り、実行しようとしているものを処理する関数を TRIGGER するか、アプリケーションで処理します。個人的には TRIGGERS を使用して行うので、データベースは独自のエンティティのままであり、データの整合性を維持するために何かに依存する必要はありません。

delimiter //

CREATE TRIGGER soft_delete_child AFTER UPDATE ON db.users FOR EACH ROW BEGIN IF NEW.deleted_at <> OLD.deleted_at THEN UPDATE events SET deleted_at=NEW.deleted_at WHERE events.user_id=NEW.id; END IF; 終わり;

// デリミタ;

于 2015-01-16T14:22:35.557 に答える