我有一个雄辩的模型,想跟踪随着时间的推移所做的每一个变化。我在模型上启用了软删除,该部分工作正常。
当我想保存模型时,我克隆它,删除原始模型并保存克隆。通过这种方式,我可以看到模型随时间的每一次变化。
我想做的是,在调用普通模型时,模型本身内置了模仿这种行为的逻辑 - > save()。
这可能吗?
答案 0 :(得分:1)
当然,您可以使用事件来执行此操作。在您的模型上,例如:
protected static function boot() {
parent::boot();
self::saving(function (Model $model) {
if ($model->isDirty()) {
// clone the $model here
}
});
self::saved(function (Model $model) {
if ($model->isDirty()) {
// delete the model here
}
});
}
您会注意到我同时使用saving
和saved
个事件。我故意这样做,以便您可以在更新数据之前克隆模型(通过从数据库重新检索模型或使用模型中存储的原始数据),然后在更新模型之前不会删除模型。保存到数据库中,为您提供您尝试实现的模式。
但是,对于记录,我不喜欢这种版本的版本。您如何知道记录是否实际被删除或仅仅是历史项目?使用此方法考虑关系的变化也很困难。我更喜欢日志样式(您可以在其中保存已更改的值的序列化列表,并根据需要进行转换)。这将导致数据库本身中的数据更少(因为您理想情况下只保存已更改的列),更明确定义的数据结构,以及由多态关系管理的中央表中的所有已记录更新。
如果你想按自己的方式去做,我认为更好的方法是克隆模型并删除克隆。我认为,这种方式对用户的破坏性较小,因为ID等不会不断变化,并且可能对其他用户来说已经过时。无论如何,我更愿意做一个序列化列表。
答案 1 :(得分:1)
我喜欢Josh的回答,尤其是isDirty
支票。我建议的一个主要变化是创建一个单独的数据库表和单独的模型。将表命名为_revisions
后缀,然后您甚至可以建立关系以轻松获取该模型的修订。
例如,如果您的实体被称为Post
,那么post_revisions
表应该是相同的,除了引用原始模型的其他post_id
列。
class PostRevision {
protected $table = 'post_revisions';
public function post() {
return $this->belongsTo(Post::class);
}
}
class Post {
protected $table = 'posts';
public function revisions() {
return $this->hasMany(PostRevision::class);
}
}
现在你的帖子表没有乱七八糟的修改