plank/laravel-checkpoint

一个用于保存模型修订历史以及按旧日期访问数据的包。

v2.1.0 2022-03-21 22:13 UTC

README

Latest Version on Packagist GitHub Tests Action Status Total Downloads

目录

为什么使用这个包

你需要存储模型随时间变化的状态吗?你需要一种方法来查询和查看模型在各个时间点的状态吗?如果是这样的话,这个包就是为你准备的!

安装

你可以通过composer安装这个包

composer require plank/laravel-checkpoint

概念

时间线

时间线 是一种完全独立查看内容的方式。时间线允许你根据模型所属的时间线来过滤模型的 修订

表: timelines

检查点

检查点 是一个感兴趣的时间点。检查点允许你根据检查点的 checkpoint_date 来过滤模型的 修订

表: checkpoints

修订

修订 引用了模型在特定时间点特定状态下的记录。当这个包启用时,你在模型上使用 HasRevisions 特性,Laravel 中模型实例的概念就改变了。由于我们想存储模型的 修订,并使它们在其不同状态下可搜索,因此实体(模型的实例)与一个唯一id关联的概念就不再正确。每个模型的每个 修订 在表中都有自己的唯一id,即使它们表示同一个实体。

相同的实体通过 original_revisionable_id 字段进行链接。

表: revisions

使用方法

修订模型

要让模型可修订,你只需要让它使用 HasRevisions 特性。

什么会被修订?

这个包通过在模型状态有意义变化时在数据库中为模型创建新行来处理修订。

启动修订命令

如果你有一个已经存在并且数据库中已经填充了模型的现有项目,可以使用 php artisan checkpoint:start 命令开始修订所有使用 HasRevsions 特性的模型。

查询作用域

这个包通过添加作用域(以及一个全局作用域)来查询具有修订的模型来实现它的目标。

活动检查点

通过设置活动检查点 Checkpoint::setActive($checkpoint),所有对修订模型的查询都将作用域到那个 $checkpoint。此外,当设置了活动检查点时,任何新创建的修订都将与那个 $checkpoint 关联。

at($moment)

/**
 * @param $moment Checkpoint|Carbon|string
 */
at($moment = null)

这是添加到具有 修订 的所有模型查询上的默认全局查询作用域。

此查询范围将限制查询仅返回具有最大主键的模型,其中修订版是在给定时刻或之前创建的。

这个时刻可以是Checkpoint的一个实例,使用其checkpoint_date字段,也可以是日期的字符串表示,或者是一个Carbon实例。

since($moment)

/**
 * @param $moment Checkpoint|Carbon|string
 */
since($moment = null)

此查询范围将限制查询仅返回具有最大主键的模型,其中修订版是在给定时刻之后创建的。

这个时刻可以是Checkpoint的一个实例,使用其checkpoint_date字段,也可以是日期的字符串表示,或者是一个Carbon实例。

temporal($upper, $lower)

/**
 * @param $upper Checkpoint|Carbon|string
 * @param $upper Checkpoint|Carbon|string
 */
temporal($until = null, $since = null)

此查询范围将限制查询仅返回在$until之前或同时创建的最大主键的模型。此方法还可以限制查询到在$since之后创建的最大主键的模型

每个参数相互独立,且$until$since可以是Checkpoint的一个实例,使用其checkpoint_date字段,也可以是日期的字符串表示,或者是一个Carbon实例。

withoutRevisions()

withoutRevisions()

此查询范围用于查询不考虑修订的模型。

动态关系

https://reinink.ca/articles/dynamic-relationships-in-laravel-using-subqueries的启发,此包提供了一些动态关系作为方便导航模型修订历史的便利。以下范围将运行子查询以获取额外的列并预加载相应的关联,从而节省您在修订可模型表中的每个表上缓存它们的麻烦。当不应用这些范围时,我们使用获取转换器来运行查询和获取相同的列,确保关联始终可用,但代价是运行更多查询。注意:应用这些范围时,您的模型属性中将有额外的列,任何更新或插入操作都将无法工作。

withNewestAt($until, $since)

/**
 * @param $until Checkpoint|Carbon|string
 * @param $since Checkpoint|Carbon|string
 */
withNewestAt($until = null, $since = null)

此范围将根据until / since约束检索最新模型的id。存储在新est_id属性中,这允许您使用->newest()关系作为快速导航到该模型的方法。默认为修订历史中的最新模型。

withNewest()

此范围是withNewestAt的快捷方式,具有默认参数。使用相同的属性、转换器和关系。

withInitial()

此范围将检索从其修订历史中检索的初始模型的id。存储在initial_id属性中,这允许您使用->initial()关系作为快速导航到修订历史中第一个项目的便捷方法。

withPrevious()

此范围将检索从其修订历史中检索的前一个模型的id。存储在previous_id属性中,这允许您使用->previous()关系作为快速导航到修订历史中前一个项目的便捷方法。

withNext()

此范围将检索从其修订历史中检索的下一个模型的id。存储在next_id属性中,这允许您使用->next()关系作为快速导航到修订历史中下一个项目的便捷方法。

修订元数据 & 唯一性

作为解决某些包兼容性问题的解决方案,此包提供了一种方便的方式来将某些列的值作为在修订版表上的元数据存储。此功能的主要用例是处理对模型的表强制某种唯一约束的列或索引。

例如,想象一下我们想要修订的 Room 模型,它有一个需要唯一的 code 字段。由于需要存在多个相同的 Room 实例作为修订,因此会有重复的 codes。通过在 Room Modelprotected $revisionMeta; 中指定 code 字段,此包将通过在 Revision 上存储它作为元数据来管理该字段。该包通过覆盖模型上的 getAttributeValue($value) 方法来实现这一点,从 Revision 中检索 code 的值。当保存 Room 的新 Revision 时,code 将自动保存到修订的 metadata 字段,并在 Room 上设置为 null。

忽略的字段

当更新 Model 的字段时,某些字段可能不值得创建 Model 的新 Revision。您可以通过设置正在修订的模型上的 protected $ignored 数组来防止在更新特定字段时创建新的 Revision

应该修订

如果您有更复杂的情况,在更新 Model 时可能不希望创建新的 Revision,您可以覆盖正在修订的 Model 上的 public function shouldRevision()。当此方法返回一个真实值时,在更新时将创建新的 Revision,当它返回一个假值时则不会。

排除列

当创建 Model 的新 Revision 时,可能有一些字段复制它们的值没有意义。在这种情况下,您可以将这些值添加到您正在修订的 Model 上的 protected $excluded 数组中。某些操作,如删除/恢复/修订子项需要完整复制,将忽略此选项。

排除关系

当创建 Model 的新 Revision 时,可能有一些关系没有复制它们的必要。在这种情况下,您可以将这些关系的名称添加到您正在修订的 Model 上的 protected $excludedRelations 数组中。排除所有与 Checkpoint 和其他相关 Revision 的关系由该包处理。

测试

composer test

变更日志

有关最近更改的详细信息,请参阅 CHANGELOG

贡献

有关详细信息,请参阅 CONTRIBUTING

安全性

如果您发现任何安全相关的问题,请通过电子邮件 massimo@plankdesign.com 而不是使用问题跟踪器。

致谢

许可

MIT 许可证 (MIT)。有关更多信息,请参阅 许可文件