joshbrw/revisionable-uuid

是 VentureCraft/Revisionable 的分支,支持基于 UUID 的键。

v1.30.0 2017-09-01 15:29 UTC

README

Revisionable

Laravel 4.x Laravel 5.2 Latest Version Downloads License

你希望为项目中任何模型都保留一个修订历史,而不必为此做任何工作吗?只需简单地从你的模型扩展 revisionable,你就可以立即拥有这样的功能,并能显示类似以下的历史记录:

  • Chris 将标题从 'Something' 改为 'Something else'
  • Chris 将类别从 'News' 改为 'Breaking news'
  • Matt 将类别从 'Breaking news' 改为 'News'

因此,你不仅可以看到发生了什么,还可以看到是谁做的,这样就有了责任归属。

Revisionable 是一个 laravel 包,允许你无需思考就能为你的模型保留修订历史。有关背景和详细信息,请参阅这篇文章

与第三方 Auth / Eloquent 扩展一起工作

Revisionable 支持 Sentry by Cartalyst 驱动的 Auth

Revisionable 现在也可以作为一个特性使用,因此你的模型可以继续扩展 Eloquent,或任何扩展 Eloquent 的类(如 Ardent)。

安装

Revisionable 可以通过 composer 安装,详细信息请参见 packagist,这里。

将以下内容添加到你的项目的 composer.json 文件的 require 部分

"venturecraft/revisionable": "1.*",

运行 composer update 下载该包

php composer.phar update

最后,你还需要在包上运行迁移(Laravel 5.x)

php artisan migrate --path=vendor/venturecraft/revisionable/src/migrations

对于 Laravel 4.x 用户

php artisan migrate --package=venturecraft/revisionable

如果你经常需要完全迁移上下文(使用 migrate:refresh),你可以做的一件事是将迁移文件从包复制到你的 app/database 文件夹,并将类名从 CreateRevisionsTable 改为类似 CreateRevisionTable 的名称(不带 's',否则你会得到一个错误消息,指出有重复的类)

cp vendor/venturecraft/revisionable/src/migrations/2013_04_09_062329_create_revisions_table.php app/database/migrations/

文档

实现

新的,基于特性的实现

对于你想要保留修订历史记录的任何模型,包含 revisionable 命名空间并在你的模型中使用 RevisionableTrait,例如,如果你正在使用另一个可启动的特性,请确保在你的模型中重写 boot 方法;

namespace MyApp\Models;

class Article extends Eloquent {
    use \Venturecraft\Revisionable\RevisionableTrait;

    public static function boot()
    {
        parent::boot();
    }
}

作为一个特性,revisionable 现在可以与标准的 Eloquent 模型一起使用,或者与任何扩展 Eloquent 的类一起使用,例如 Ardent

特性需要 PHP >= 5.4

基于类的历史实现

新的基于特性的方法与现有的 Revisionable 安装向后兼容。你仍然可以使用下面的安装说明,这本质上是一个特性的包装器。

对于你想要保留修订历史记录的任何模型,包含 revisionable 命名空间并扩展 revisionable 而不是 eloquent,例如

use Venturecraft\Revisionable\Revisionable;

namespace MyApp\Models;

class Article extends Revisionable { }

注意它也适用于命名空间化的模型。

实现说明

如有需要,您可以通过在模型中将 $revisionEnabled 设置为 false 来禁用版本控制。这在您想暂时禁用版本控制,或想创建一个扩展了可修订性的基础模型(所有模型都继承该模型)但想关闭某些模型的版本控制时,会很有用。

namespace MyApp\Models;

class Article extends Eloquent {
    use Venturecraft\Revisionable\RevisionableTrait;

    protected $revisionEnabled = false;
}

您还可以在进行了 X 次修订后禁用版本控制,通过将 $historyLimit 设置为希望停止修订的修订次数。

namespace MyApp\Models;

class Article extends Eloquent {
    use Venturecraft\Revisionable\RevisionableTrait;

    protected $revisionEnabled = true;
    protected $historyLimit = 500; //Stop tracking revisions after 500 changes have been made.
}

为了限制历史记录,但您想删除旧修订而不是停止跟踪修订,可以通过设置 $revisionCleanup 来实现该功能。

namespace MyApp\Models;

class Article extends Eloquent {
    use Venturecraft\Revisionable\RevisionableTrait;

    protected $revisionEnabled = true;
    protected $revisionCleanup = true; //Remove old revisions (works only when used with $historyLimit)
    protected $historyLimit = 500; //Maintain a maximum of 500 changes at any point of time, while cleaning up old revisions.
}

存储软删除

默认情况下,如果您的模型支持软删除,revisionable 会将其存储和任何恢复作为模型的更新。

您可以通过将 deleted_at 添加到您的 $dontKeepRevisionOf 数组中来选择忽略删除和恢复。

为了更好地格式化 deleted_at 条目的输出,您可以使用 isEmpty 格式化器(请参阅 格式化输出 以获取示例)。

存储创建

默认情况下,新模型的创建不会被存储为修订。只有模型的后续更改会被存储。

如果您想将创建存储为修订,可以通过在模型中添加以下内容来覆盖此行为,将 revisionCreationsEnabled 设置为 true

protected $revisionCreationsEnabled = true;

更多控制

无疑,会有一些情况您只想为模型的某些字段存储修订历史,这支持两种不同的方式。在您的模型中,您可以选择明确指定您想要跟踪的字段,而忽略其他字段

protected $keepRevisionOf = array(
    'title'
);

或者,您可以指定明确不想要跟踪的字段。所有其他字段将被跟踪。

protected $dontKeepRevisionOf = array(
    'category_id'
);

$keepRevisionOf 设置比 $dontKeepRevisionOf 优先。

事件

每次创建模型修订时都会触发一个事件。您可以监听 revisionable.created
revisionable.savedrevisionable.deleted

// app/Providers/EventServiceProviders.php
public function boot(DispatcherContract $events)
{
    parent::boot($events);

    $events->listen('revisionable.*', function($model, $revisions) {
        // Do something with the revisions or the changed model. 
        dd($model, $revisions);
    });
}

输出格式

您可以使用 eloquent accessors 在模型中设置值的输出,请参阅 Laravel 文档 了解有关访问器的更多信息。以下文档已被弃用

在您想控制值输出格式的情况下,例如布尔字段,您可以在模型中将它们设置为 $revisionFormattedFields 数组中的值。例如,

protected $revisionFormattedFields = array(
    'title'  => 'string:<strong>%s</strong>',
    'public' => 'boolean:No|Yes',
    'modified' => 'datetime:m/d/Y g:i A',
    'deleted_at' => 'isEmpty:Active|Deleted'
);

您还可以使用模型中的 $revisionFormattedFieldNames 数组覆盖字段名输出,例如,

protected $revisionFormattedFieldNames = array(
    'title' => 'Title',
    'small_name' => 'Nickname',
    'deleted_at' => 'Deleted At'
);

当您使用 $revision->fieldName() 输出修订字段名时,这就会发挥作用。

字符串

要格式化字符串,只需在值前加上 string: 并确保包含 %s(这是实际值将出现在格式化响应中的位置),例如,

string:<strong>%s</strong>

布尔值

布尔值默认将显示为 0 或 1,这相当平淡,对最终用户来说意义不大,因此可以使用此格式化器输出更友好的内容。在值前加上 boolean: 并然后通过管道添加您的 false 和 true 选项,例如,

boolean:No|Yes

日期时间

默认情况下,日期时间将显示为 Y-m-d H:i:s。在值前加上 datetime: 并然后添加您的日期时间格式,例如,

datetime:m/d/Y g:i A

Is Empty

这基于布尔值,但不是测试 true 或 false 值,而是检查值是否为 null 或空字符串。

isEmpty:No|Yes

这也可以接受 %s 如果您想输出值,如下所示,如果值为空,将显示 'Nothing',如果存在则显示实际值

isEmpty:Nothing|%s

加载修订历史

要加载给定模型的修订历史,只需在该模型上调用 revisionHistory 方法,例如,

$article = Article::find($id);
$history = $article->revisionHistory;

显示历史记录

大部分情况下,修订历史将包含足够的信息以直接输出变更历史,但在外键更新时,我们需要能够进行一些映射,并显示比 plan_id 从 3 更改为 1 更友好的内容。

为此,有几个辅助方法可以显示更深入的信息,因此您可以显示类似 Chris 将计划从青铜更改为黄金 的内容。

上面的结果将来自以下内容

@foreach($account->revisionHistory as $history )
    <li>{{ $history->userResponsible()->first_name }} changed {{ $history->fieldName() }} from {{ $history->oldValue() }} to {{ $history->newValue() }}</li>
@endforeach

如果您还启用了创建修订版本,您可以这样显示

@foreach($resource->revisionHistory as $history)
  @if($history->key == 'created_at' && !$history->old_value)
    <li>{{ $history->userResponsible()->first_name }} created this resource at {{ $history->newValue() }}</li>
  @else
    <li>{{ $history->userResponsible()->first_name }} changed {{ $history->fieldName() }} from {{ $history->oldValue() }} to {{ $history->newValue() }}</li>
  @endif
@endforeach

userResponsible()

返回负责进行修订的用户。返回用户模型,如果没有用户记录则返回 null。

加载的用户模型取决于您在 config/auth.php 文件中为 model 变量设置的配置。

fieldName()

返回更新的字段的名称,如果更新的字段是外键(在当前阶段,它只是检查字段是否有 _id 后缀),则返回 _id 之前的文本。例如,如果字段是 plan_id,则返回 plan

记住,您可以通过在模型中覆盖 $revisionFormattedFieldNames 数组来覆盖字段名称的输出。

identifiableName()

当值(旧值或新值)是外键关系ID时使用。

默认情况下,它将简单地返回已更新的模型ID。您可以根据自己的模型覆盖此方法以返回有意义的值。例如,

use Venturecraft\Revisionable\Revisionable;

class Article extends Revisionable
{
    public function identifiableName()
    {
        return $this->title;
    }
}

oldValue() 和 newValue()

获取更新前或更新后的模型值。如果是外键,则调用 identifiableName()。

作为修订版本的外键未知或无效

在旧值或新版本的值是不再存在的外键或实际上是空值的情况下,您可以在模型中设置两个变量来控制这些情况下的输出

protected $revisionNullString = 'nothing';
protected $revisionUnknownString = 'unknown';

disableRevisionField()

有时暂时禁用可修订字段可能会有所帮助,如果您想保存更新但不需要记录更改。

$object->disableRevisionField('title'); // Disables title

$object->disableRevisionField(array('title', 'content')); // Disables title and content

贡献

鼓励并欢迎贡献;为了保持有序,所有错误和请求都应在主项目的 GitHub 问题标签中打开,请访问 venturecraft/revisionable/issues

所有拉取请求都应提交到 develop 分支,以便在合并到 master 分支之前进行测试。

遇到问题了吗?

如果您在使用此包时遇到问题,很可能会有人遇到过相同的问题。您可以在以下两个地方查找对您问题的常见答案

如果您更喜欢在 StackOverflow 上公开发布您的问题,请使用 'revisionable' 标签。