asc/revisionable

无需思考即可为您的模型保留版本历史,作为Laravel 4的包创建

1.15.0 2015-02-25 00:35 UTC

README

Revisionable

如果您想在项目中为任何模型保留版本历史而不需要做任何工作,那岂不是很好?只需简单地从您的模型扩展revisionable,您就可以立即拥有它,并能够显示类似这样的历史

  • Chris将标题从'Something'更改为'Something else'
  • Chris将类别从'新闻'更改为'重大新闻'
  • Matt将类别从'重大新闻'更改为'新闻'

因此,您不仅可以查看发生了什么,还可以知道是谁做的,因此具有问责制。

Revisionable是一个laravel包,允许您在无需思考的情况下为模型保留版本历史。有关背景信息和信息,请参阅这篇文章

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

Revisionable支持由以下Auth提供的功能:

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

安装

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

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

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

运行composer update以下载包

php composer.phar update

最后,您还需要运行包的迁移

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,例如:

namespace MyApp\Models;

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

作为一个特质,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;
}

存储软删除

默认情况下,如果您的模型支持软删除,修订版本功能将存储这些删除和恢复操作,并在模型上作为更新存储。

您可以选择忽略删除和恢复操作,只需在您的 $dontKeepRevisionOf 数组中添加 deleted_at 即可。

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

更多控制

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

protected $keepRevisionOf = array(
    'title'
);

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

protected $dontKeepRevisionOf = array(
    'category_id'
);

$keepRevisionOf 设置优先于 $dontKeepRevisionOf

格式输出

您可以继续(并且鼓励)在您的模型中使用 eloquent 访问器 来设置值的输出,有关访问器的更多信息,请参阅 Laravel 文档。以下文档已过时

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

protected $revisionFormattedFields = array(
    'title'  => 'string:<strong>%s</strong>',
    'public' => 'boolean:No|Yes',
    '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

是否为空

这依赖于布尔值,但不是测试 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

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()。

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

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

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

disableRevisionField()

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

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

或者

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

贡献

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

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

遇到麻烦了吗?

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

如果你更喜欢在StackOverflow上公开提问,请使用'revisionable'标签。