codekanzlei/cake-model-history

CakePHP3的ModelHistory插件

安装: 14,904

依赖项: 3

建议者: 0

安全: 0

星标: 6

关注者: 3

分支: 1

开放问题: 2

类型:cakephp-plugin

v3.0.0-rc1 2017-10-17 08:29 UTC

README

CakePHP 3 Model History Plugin

Build Status codecov License

CakePHP 3 数据库记录的历史化。跟踪用户执行的改变,并提供可定制的视图元素来显示它们。

需求

安装

1. 在你的composer.json中要求插件

"require": {
    "codekanzlei/cake-model-history": "2.0.*",
}

在你的项目文件夹中打开终端并运行以下命令

`$ composer update`

2. 配置config/bootstrap.php

加载 插件

Plugin::load('ModelHistory', ['bootstrap' => false, 'routes' => true]);

由于所有对记录的改变都保存到ModelHistoryTabledata字段(类型MEDIUMBLOB),格式为JSON,你必须使用自定义的类型映射

Type::map('json', 'CkTools\Database\Type\JsonType');

3. 在你的项目数据库中创建一个model_history

我们必须通过迁移插件的帮助来创建数据库模式。

    $ bin/cake migrations migrate -p ModelHistory

4. AppController.php

$helpers

public $helpers =  [
    'ModelHistory.ModelHistory'
]

用法与配置

表设置

在你的要使用model-history的Tableinitialize函数中添加Historizable Behavior。

$this->addBehavior('ModelHistory.Historizable');

注意:默认情况下,model-history插件将数据库记录的属性更改追踪到执行并保存它们的用户,通过比较UsersTable中的表字段'firstname'和'lastname'(见HistorizableBehavior.php中的$_defaultConfig以了解这些默认设置)。如果你的字段不叫'firstname'和'lastname',你可以很容易地根据你的UsersTable中的字段名自定义这些设置,如下所示

$this->addBehavior('ModelHistory.Historizable', [
    'userNameFields' => [
        'firstname' => 'User.your_first_name_field',
        'lastname' => 'Users.your_last_name_field',
        'id' => 'Users.id'
    ],
    'userIdCallback' => null,
    'entriesToShow' => 10,
    'fields' => [],
    'associations' => [],
    'ignoreFields' => []
]);

默认情况下,ModelHistory监视表模式中找到的每个字段的更改。它试图从数据类型推断出要使用的数据类型,并混淆所有包含"password"的字段。否则,默认值是'searchable' => true'saveable' => true'obfuscated' => false

要覆盖特定设置,将一个数组添加到'fields'数组中,并列出你想覆盖的值。

$this->addBehavior('ModelHistory.Historizable', [
    'fields' => [
    // The field name
        'firstname' =>[
            // Allowed translation forms: String, Closure returning string
            // Its recommended to use the closure, so translations are made after core initialize when the correct language was set.
            'translation' => function () {
                return __('user.firstname');
            },
            // The searchable indicator is used to show the field in the filter box
            // defaults to true
            'searchable' => true,
            // The savable indicator is used to decide whether the field is tracked
            // defaults to true
            'saveable' => true,
            // obfuscate the values of the field in the history view.
            // defaults to false except for fieldnames containing "password"
            'obfuscated' => false,
            // Allowed: string, bool, number, relation, date, hash, array, association, mass_association.
            'type' => 'string',
            // Optional display parser to modify the value before displaying it,
            // if no displayParser is found, the \ModelHistory\Model\Transform\{$type}Transformer is used.
            'displayParser' => function ($fieldname, $value, $entity) {
                return $value;
            },
            // Optional save parser to modify the value before saving the history entry
            'saveParser' => function ($fieldname, $value, $entity) {
                return $value;
            },
        ],
    ]
]);

由于默认监视的字段仅限于表中,所以n:m关联以及在其他表中具有外键的关联必须至少配置类型。以下是从一个UsersTable中的三个真实世界示例

$this->addBehavior('ModelHistory.Historizable', [
    'fields' => [
        'customer_id' => [
            'saveable' => false,
            'type' => 'association'
        ],
        'regions' => [
            'type' => 'mass_association',
            'displayParser' => function ($fieldName, $value, $entity) {
                if (is_array($value)) {
                    return implode(', ', $value);
                }

                return $value;
            }
        ],
        'contact' => [
            'type' => 'string',
            'saveParser' => function ($fieldName, $value, $entity) {
                return __('user.associated_contact');
            },
            'displayParser' => function ($fieldName, $value, $entity) {
                return __('user.associated_contact');
            }
        ],
    ]
]);

类型

  • string:用于字符串值。
  • bool:用于布尔值。
  • number:用于整数值。
  • date:用于日期值。
  • hash:用于关联数组。
  • array:用于顺序(索引)数组。
  • relation:用于1到n关系。
  • association:用于n到m关系。
  • mass_association:用于应压缩为一个历史条目的n到m关系。

三种类型relationassociationmass_association能够链接到关联实体。默认url为

'url' => [
    'plugin' => null,
    'controller' => $entityController // automatically set to the entities controller
    'action' => 'view'
]

默认url可以被覆盖:在行为数组中的url覆盖默认值,而在字段配置中定义的url具有最高优先级。

$this->addBehavior('ModelHistory.Historizable', [
    'url' => [
        'plugin' => 'Admin',
        'action' => 'index'
    ],
    'fields' => [
        'firstname' => [
            'translation' => function () {
                return __('user.firstname');
            },
            'searchable' => true,
            'saveable' => true,
            'obfuscated' => false,
            'type' => 'relation',
            'url' => [
                'plugin' => 'Special',
                'action' => 'show'
            ]
        ],
    ]
]);

如果要在源实体的条目中查看已保存关联的条目,您可以指定 associations 键。它必须与源实体中给出的对象属性键匹配。此外,模型历史区域必须获取 includeAssociated 选项,其值为 true

$this->addBehavior('ModelHistory.Historizable', [
    'fields' => [
        ...
    ],
    'associations' => [
        'contact',
        'contact.address'
    ]
]);

为了进一步指定实体保存的上下文,并收集更多信息,您可以在实体中实现 \ModelHistory\Model\Entity\HistoryContextTrait。您必须在实体上调用 setHistoryContext 以添加上下文信息。目前有三种上下文类型:ModelHistory::CONTEXT_TYPE_CONTROLLERModelHistory::CONTEXT_TYPE_SHELLModelHistory::CONTEXT_TYPE_SLUG。当在实体的 typeDescriptions 中定义时,可选的 slug 会自动翻译。

    /**
     * Index action of a controller
     */
    public function index()
    {
        if ($this->request->is(['post'])) {
            $entity = $this->Table->newEntity($this->request->data);
            $entity->setHistoryContext(ModelHistory::CONTEXT_TYPE_CONTROLLER, $this->request, 'optional_slug');
            $this->Table->save($entity);
        }
    }

您还可以在实体内部指定上下文获取器以搜索定义的上下文。请注意,您必须使用来自 CkToolsTypeAwareTrait

    use \CkTools\Utility\TypeAwareTrait;

    /**
     * Retrieve defined contexts
     *
     * @return void
     */
    public static function getContexts()
    {
        return self::getTypeMap(
            self::CONTEXT_TYPE_FORGOT_PASSWORD
        );
    }

忽略字段

默认情况下,字段 idcreatedmodified 不会被跟踪。如果您想覆盖要忽略或不忽略的字段,请在配置数组中提供 ignoreFields,并且只有那些字段将被忽略。

$this->addBehavior('ModelHistory.Historizable', [
    'ignoreFields' => [
        'secret_field',
        'created'
    ]
]);

视图设置

使用 ModelHistoryHelper.php 创建包含一条记录更改历史的 neat 视觉元素,在您的视图中只需调用一次即可。

<?= $this->ModelHistory->modelHistoryArea($user); ?>

modelHistoryArea 有以下 选项:

  • showCommentBox (false)

    此外,还渲染一个评论字段(输入类型文本)。用户输入将被保存到模型历史表。

  • showFilterBox (false)

    此外,还渲染一个筛选框,可以用来搜索条目。

  • includeAssociated (false)

    此外,包括所有保存的关联。

为了使模型历史区域获取其数据,请将 'ModelHistory' 组件添加到您的 Frontend.AppController 中的 baseComponents 属性,在 /webroot/js/app/app_controller.js 下。如果您尚未设置 FrontendBridge,请按照这些步骤进行。在那里您也会找到该文件的模板。

确保 app_controller.js 已加载到您想显示模型历史区域的页面。然后,ModelHistory JS-Component 将根据您给定的辅助方法的 $entity 发送 AJAX 请求到 /model_history/ModelHistory/index/$modelName/$primaryKey,并自行填充模型历史区域。