josegonzalez/cakephp-version

CakePHP ORM行为,允许记录版本控制

5.0.0 2024-01-09 14:55 UTC

This package is auto-updated.

Last update: 2024-09-09 16:22:13 UTC


README

Build Status Coverage Status Total Downloads Latest Stable Version Documentation Status Gratipay

版本

一个用于方便版本化数据库实体的CakePHP 4.x插件

安装

将以下行添加到您的应用程序的composer.json

"require": {
    "josegonzalez/cakephp-version": "dev-master"
}

然后执行以下命令

composer update

或者直接运行以下命令而不更改您的composer.json

composer require josegonzalez/cakephp-version:dev-master

使用方法

在您的应用程序的config/bootstrap.php中添加

Plugin::load('Josegonzalez/Version', ['bootstrap' => true]);

使用方法

运行以下模式迁移

CREATE TABLE `version` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `version_id` int(11) DEFAULT NULL,
    `model` varchar(255) NOT NULL,
    `foreign_key` int(10) NOT NULL,
    `field` varchar(255) NOT NULL,
    `content` text NULL,
    `created` datetime NOT NULL,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

请注意,如果要在应用程序中版本化任何可空字段,则content字段必须是可空的。

您还可以选择将类型为integerversion_id字段添加到正在版本化的表中。这将存储给定页面的最新版本号。

如果您希望使用cakephp/migrations创建表,则需要使用类似于以下内容的迁移

<?php

use Phinx\Migration\AbstractMigration;

class CreateVersions extends AbstractMigration
{
    public function change()
    {
        $this->table('version')
             ->addColumn('version_id', 'integer', ['null' => true])
             ->addColumn('model', 'string')
             ->addColumn('foreign_key', 'integer')
             ->addColumn('field', 'string')
             ->addColumn('content', 'text', ['null' => true])
             ->addColumn('created', 'datetime')
             ->create();
    }
}

将以下行添加到您的实体中

use \Josegonzalez\Version\Model\Behavior\Version\VersionTrait;

然后将在实体类中包含该特质

class PostEntity extends Entity {
    use VersionTrait;
}

通过以下方式在您想要应用行为的模型中附加行为

public function initialize(array $config) {
    $this->addBehavior('Josegonzalez/Version.Version');
}

无论通过插入还是更新持久化实体时,该实体也会被持久化到version表中。您可以通过以下代码访问特定版本

// Will contain a generic `Entity` populated with data from the specified version.
$version = $entity->version(1);

您可以选择检索所有版本

$versions = $entity->versions();

存储额外元数据

cakephp-version触发一个事件Model.Version.beforeSave,您可以选择处理它以附加有关版本的额外元数据。

将必要的额外字段添加到您的迁移中,例如

CREATE TABLE `version` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `version_id` int(11) DEFAULT NULL,
    `model` varchar(255) NOT NULL,
    `foreign_key` int(10) NOT NULL,
    `field` varchar(255) NOT NULL,
    `content` text,
    `created` datetime NOT NULL,
    `custom_field1` varchar(255) NOT NULL, /* column to store our metadata */
    `custom_field2` varchar(255) NOT NULL, /* column to store our metadata */
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

然后定义一个事件监听器来处理事件并传递额外的元数据,例如

use Cake\Event\Event;
use Cake\Event\EventListenerInterface;

class VersionListener implements EventListenerInterface {

    public function implementedEvents() {
        return array(
            'Model.Version.beforeSave' => 'insertAdditionalData',
        );
    }

    public function insertAdditionalData(Event $event) {
        return [
            'custom_field1' => 'foo',
            'custom_field2' => 'bar'
        ];
    }
}

然后您可以将事件监听器附加到项目中,例如

use App\Event\VersionListener;
use Cake\Event\EventManager;

$VersionListener = new VersionListener();
EventManager::instance()->on($VersionListener);

请注意,处理此事件还可以允许您修改/覆盖插件生成的值。这可以提供有用的功能,但请确保如果您的事件监听器返回的数组键名为version_idmodelforeign_keyfieldcontentcreated,则这是预期的行为。

将user_id作为元数据存储

user_id作为额外元数据存储,最简单的方法是结合使用Muffin/Footprint。上面的insertAdditionalData()方法可能如下所示

    /**
     * @param \Cake\Event\Event $event
     *
     * @return array
     */
    public function insertAdditionalData(Event $event)
    {
        $data = [
            ...
        ];

        if ($event->data('_footprint')) {
            $user = $event->data('_footprint');
            $data += [
                'user_id' => $user->id,
            ];
        }

        return $data;
    }

使用FootprintAwareTrait的任何控制器将然后提供_footprint数据到模型层,以便此事件回调使用。

Bake集成

如果您使用'bootstrap' => true加载插件,则可以使用该插件通过正确命名的数据库表自动检测使用情况。为此,只需创建一个表,其模式如上所述,命名为您想要修订的表名加上后缀_versions。例如,要修订以下表

CREATE TABLE `posts` (
    `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
    `category_id` int(11) DEFAULT NULL,
    `user_id` int(11) DEFAULT NULL,
    `status` varchar(255) NOT NULL DEFAULT 'published',
    `visibility` varchar(255) NOT NULL DEFAULT 'public',
    `title` varchar(255) NOT NULL DEFAULT '',
    `route` varchar(255) DEFAULT NULL,
    `content` text,
    `published_date` datetime DEFAULT NULL,
    `created` datetime NOT NULL,
    `modified` datetime NOT NULL,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

创建以下表

CREATE TABLE `posts_versions` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `version_id` int(11) NOT NULL,
    `model` varchar(255) NOT NULL,
    `foreign_key` int(11) NOT NULL,
    `field` varchar(255) NOT NULL,
    `content` text,
    `created` datetime NOT NULL,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

您可以使用以下bake命令为此创建迁移

bin/cake bake migration create_posts_versions version_id:integer model foreign_key:integer field content:text created

您还希望将此迁移中的content字段设置为可空的,否则您将无法修订可空的字段。

要跟踪posts表中的当前版本,您可以为该表创建一个迁移以添加version_id字段

bin/cake bake migration add_version_id_to_posts version_id:integer

配置

有五种行为配置可以使用

  • versionTable:(默认:version)用于存储版本化数据的表名。在版本化多种类型的实体时,使用不同的表可能很有用。
  • versionField: (默认:version_id) 用于存储当前版本的版本化表中字段的名称。如果缺失,插件将继续正常工作。
  • additionalVersionFields: (默认 ['created']) 将公开的版本化表的附加或自定义字段。默认以 version_ 为前缀,例如 'version_user_id' 对应于 'user_id'
  • referenceName: (默认:数据库表名称) 用于在版本表中识别记录的区分符。
  • onlyDirty: (默认:false) 设置为 true 以仅对脏属性进行版本控制。