stabbre/eloquent-versioned

为 Laravel 5.2 的 Eloquent ORM 添加透明版本控制

0.1.2 2016-02-19 12:47 UTC

This package is not auto-updated.

Last update: 2024-09-25 15:38:44 UTC


README

为 Laravel 5.2 的 Eloquent ORM 添加透明版本支持。

警告:此存储库目前处于超级实验状态。我将乐意接受拉取请求和问题报告,但你可能不应该在生产环境中使用它,并且接口可能会在不通知的情况下更改(尽管重大更改将增加版本号)。

它最近还更新了,以便与 Laravel 5.2 的全局作用域保持一致,因此如果你还没有升级到 5.2,请坚持使用版本 0.0.7。

当使用此特质(并带有包含所需字段的表)时,保存模型实际上会创建一行新记录,并增加版本号。

使用全局作用域,旧版本在标准 ORM 操作(选择、更新、删除)和关系(hasOne、hasMany、belongsTo 等)中被忽略。

此包还提供了一些特殊方法来包含查询中的旧版本(或仅查询旧版本),这可以用于显示模型的历史或其他类似功能。

安装

通过 Composer 添加

composer require sbarre/eloquent-versioned --no-dev

使用 --no-dev 标志以避免下载所有测试依赖项(如整个 Laravel 框架)。

迁移

版本化模型需要您的数据库表包含 3 个字段来处理版本控制。

如果您正在创建新表或更改现有表,请将以下行包含在迁移的 up() 方法中

$table->integer('model_id')->unsigned()->default(1);
$table->integer('version')->unsigned()->default(1);
$table->integer('is_current_version')->unsigned()->default(1);
$table->index('is_current_version');
$table->index('model_id');
$table->index('version');

如果您正在修改现有表的迁移,则应将这些行包含在迁移的 down() 方法中

$table->dropColumn(['model_id','version','is_current_version']);
$table->dropIndex(['model_id','version','is_current_version']);

注意事项

如果您更改了 EloquentVersioned\VersionedBuilder 中的常量以重命名列,请记住在迁移中也进行更改。

用法

在您的 Eloquent 模型类中,首先添加对特质的 use 语句

use EloquentVersioned\Traits\Versioned;

当特质启动时,它将应用适当的范围,并覆盖各种 Eloquent 方法以支持版本化记录。

一旦应用了特质,您就可以像往常一样使用模型,标准查询的行为也像往常一样。

$project = Project::create([
    'name' => 'Project Name',
    'description' => 'Project description goes here'
])->fresh();

print_r($project->toArray());

例如,这将输出

Array
(
    [id] => 1
    [version] => 1
    [name] => Project Name
    [description] => Project description goes here
    [created_at] => 2015-05-24 17:16:05
    [updated_at] => 2015-05-24 17:16:05
)

实际的数据库行看起来像这样

Array
(
    [id] => 1
    [model_id] => 1
    [version] => 1
    [is_current_version] => 1
    [name] => Updated project Name
    [description] => Project description goes here
    [created_at] => 2015-05-24 17:16:05
    [updated_at] => 2015-05-24 17:16:05
)

然后如果您更改模型并保存

$project->name = 'Updated project name';
$project->save();

print_r($project->toArray());

这将输出

Array
(
    [id] => 1
    [version] => 2
    [name] => Updated project Name
    [description] => Project description goes here
    [created_at] => 2015-05-24 17:16:05
    [updated_at] => 2015-05-24 17:16:45
)

模型将 model_id 列更改为 id,并隐藏一些版本特定的列。实际上,这实际上是相同的数据库行,现在看起来像这样

Array
(
    [id] => 1
    [model_id] => 1
    [version] => 2
    [is_current_version] => 1
    [name] => Updated project Name
    [description] => Project description goes here
    [created_at] => 2015-05-24 17:16:05
    [updated_at] => 2015-05-24 17:16:45
)

同时插入新行以保存我们的前一个版本,现在看起来像这样

Array
(
    [id] => 2
    [model_id] => 1
    [version] => 1
    [is_current_version] => 0
    [name] => Project Name
    [description] => Project description goes here
    [created_at] => 2015-05-24 17:16:05
    [updated_at] => 2015-05-24 17:16:05
)

因此,is_current_version 属性是全局作用域所针对的,限制所有选择查询仅记录为 is_current_version = 1

在模型上调用 save() 会将原始版本复制到新行(带有 is_current_version = 0),然后增加当前模型的 version_id 属性,更改适当的时间戳,并保存它。

如果您正在对模型进行非常小的更改并且不想创建新版本,您可以调用 saveMinor() 代替。

$project->saveMinor(); // doesn't create a new version

处理旧版本的方法

如果您想检索模型的所有版本列表(或将旧版本包含在更大的查询中)

$projectVersions = Project::withOldVersions()->find(1);

如果在上述示例之后运行,这将返回包含 2 个模型的数组。

您还可以使用以下方法检索仅包含旧模型的列表

$oldVersions = Project::onlyOldVersions()->find(1);

否则,Eloquent 的 ORM 操作应该像往常一样工作,包括开箱即用的关系。

模型版本间迁移方法

如果您想以链表方式导航模型的所有版本

$current = Project::find(1);

$previous = $current->getPreviousModel();
$next = $previous->getNextModel();

// $next == $current

如果您处于最新版本,getNextModel() 将返回 null,同理,如果您处于最旧版本,getPreviousModel() 也将返回 null

支持 & 路线图

如顶部所示,此包仍处于 非常实验性 状态,并且正在积极开发中。当前路线图包括测试覆盖和更广泛的实际测试,因此欢迎提交拉取请求和问题!