stabbre / eloquent-versioned
为 Laravel 5.2 的 Eloquent ORM 添加透明版本控制
Requires
- php: >=5.4
- illuminate/database: ~5.2
Requires (Dev)
- laravel/framework: ~5.2
- phpunit/phpunit: 4.6.*
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
。
支持 & 路线图
如顶部所示,此包仍处于 非常实验性 状态,并且正在积极开发中。当前路线图包括测试覆盖和更广泛的实际测试,因此欢迎提交拉取请求和问题!