jpnut/eloquent-versioning

为Eloquent ORM提供支持版本化的扩展。

2.0.0 2020-02-10 13:56 UTC

This package is auto-updated.

Last update: 2024-09-11 02:34:49 UTC


README

Latest Version Quality Score Software License StyleCI

此包提供了一个特质,为Eloquent模型添加版本(由proai/eloquent-versioning分支而来)。

每当模型更新时,都会创建新的版本。每个模型的版本都存储在独立的表中(例如 user_versions)。

该包允许混合使用带版本和不带版本的属性。

默认情况下,查询的范围是合并父表中的记录与最新版本。存在额外的范围以合并特定版本或时间点的记录。

安装

可以通过Composer安装此包。

composer require jpnut/eloquent-versioning

用法

要将版本添加到您的模型中,您必须

  1. 实现 JPNut\Versioning\Versionable 接口。

  2. 使用 JPNut\Versioning\VersionableTrait 特质。

  3. getVersionableOptions 方法添加到您的模型中。此方法必须返回 JPNut\Versioning\VersionOptions 实例。您应该通过调用 setVersionableAttributes 并传递属性数组来定义您想要版本化的属性

    ...
    
    /**
     * @return \JPNut\Versioning\VersionOptions
     */
    public function getVersionableOptions(): VersionOptions
    {
        return VersionOptions::create()
            ->setVersionableAttributes(['email', 'city']);
    }
    
    ...
  4. version 列添加到您希望版本化的模型的表中。这跟踪当前版本。

    ...
    
    Schema::create('users', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('version')->unsigned()->nullable();
        $table->string('name');
        $table->timestamps();
        $table->softDeletes();
    });
    
    ...
  5. 创建一个表来包含版本。此表应包含对父模型的引用(parent_id),版本号 version,所有可版本化属性(emailcity),以及 created_at 时间戳。

    ...
    
    Schema::create('user_versions', function (Blueprint $table) {
        $table->integer('parent_id')->unsigned();
        $table->integer('version')->unsigned();
        $table->string('email');
        $table->string('city');
        $table->timestamp('created_at');
    
        $table->primary(['parent_id', 'version']);
    });
    
    ...

假设版本表名采用 {entity}_versions 的形式,其中 entity 是实体名词的单数形式(例如 usersuser_versions)。您可以通过调用选项对象的相应方法来覆盖此名称以及所有列名(以下显示了默认设置)。

...
   
/**
 * @return \JPNut\Versioning\VersionOptions
 */
public function getVersionableOptions(): VersionOptions
{
    return VersionOptions::create()
        ->saveVersionKeyTo('version')
        ->useVersionTable('user_versions')
        ->saveVersionTableKeyTo('version')
        ->versionTableForeignKeyName('parent_id')
        ->versionTableCreatedAtName('created_at');
}

...

示例

use Illuminate\Database\Eloquent\Model;
use JPNut\Versioning\Versionable;
use JPNut\Versioning\VersionableTrait;
use JPNut\Versioning\VersionOptions;

class YourEloquentModel extends Model implements Versionable
{
    use VersionableTrait;
    
    /**
     * @return VersionOptions
     */
    public function getVersionableOptions(): VersionOptions
    {
        return VersionOptions::create()
            ->setVersionableAttributes(['email', 'city']);
    }

    ...
}

您可以使用 atVersion 范围检索特定版本的模型

Model::atVersion(1)->find(1);

您可以使用 atTime 范围检索特定时间点的模型

Model::atTime(now()->subDay())->find(1);

请注意,这将尝试找到在给定时间之前创建的最后一个版本。如果没有此类版本,则方法将返回 null

您可以使用 withoutVersion 范围禁用全局范围

Model::withoutVersion()->find(1);

您可以通过在模型实例上调用 versions 属性(或方法)来获取所有版本的形式的关系

$model->versions;

请注意,默认情况下使用了一个通用的 Version 模型。您可以通过覆盖 versions 方法并返回自己的 HasMany 关系来更改此模型。

您可以通过调用带有所需版本作为参数的 changeVersion() 方法来回滚到之前的版本。

$model->changeVersion(1);

请注意,这将创建一个新的版本,其可版本化属性值与指定的版本相同(而不是更改父表中 version 列的值)。

测试

该包包含一些与Orchestra集成的测试用例,可以通过phpunit运行这些测试。

vendor/bin/phpunit

贡献

创建一个Pull Request!

替代方案

许可

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