codekanzlei / cake-model-history
CakePHP3的ModelHistory插件
Requires
- php: >=7.1
- codekanzlei/cake-cktools: ^1.3
- codekanzlei/cake-frontend-bridge: ^1.2
Requires (Dev)
- cakephp/cakephp: ^3.4
- cakephp/cakephp-codesniffer: ^3.0
- phpstan/phpstan: ^0.8
- phpunit/phpunit: ^6.0
- scherersoftware/coding-standard: ^3.0
This package is auto-updated.
Last update: 2024-09-21 19:55:27 UTC
README
CakePHP 3 数据库记录的历史化。跟踪用户执行的改变,并提供可定制的视图元素来显示它们。
需求
- scherersoftware cake-cktools 用于JSON到MEDIUMBLOB类型映射
- Font Awesome 面板导航按钮
安装
1. 在你的composer.json
中要求插件
"require": {
"codekanzlei/cake-model-history": "2.0.*",
}
在你的项目文件夹中打开终端并运行以下命令
`$ composer update`
2. 配置config/bootstrap.php
加载 插件
Plugin::load('ModelHistory', ['bootstrap' => false, 'routes' => true]);
由于所有对记录的改变都保存到ModelHistoryTable
的data
字段(类型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的Table
的initialize
函数中添加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关系。
三种类型relation
、association
和mass_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_CONTROLLER
、ModelHistory::CONTEXT_TYPE_SHELL
和 ModelHistory::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);
}
}
您还可以在实体内部指定上下文获取器以搜索定义的上下文。请注意,您必须使用来自 CkTools
的 TypeAwareTrait
。
use \CkTools\Utility\TypeAwareTrait;
/**
* Retrieve defined contexts
*
* @return void
*/
public static function getContexts()
{
return self::getTypeMap(
self::CONTEXT_TYPE_FORGOT_PASSWORD
);
}
忽略字段
默认情况下,字段 id
、created
和 modified
不会被跟踪。如果您想覆盖要忽略或不忽略的字段,请在配置数组中提供 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,并自行填充模型历史区域。