2017 © Pedro Peláez
 

cakephp-plugin cakephp-version

CakePHP ORM behavior to allow versioning of records

image

josegonzalez/cakephp-version

CakePHP ORM behavior to allow versioning of records

  • Monday, July 9, 2018
  • by josegonzalez
  • Repository
  • 3 Watchers
  • 45 Stars
  • 7,801 Installations
  • PHP
  • 0 Dependents
  • 0 Suggesters
  • 15 Forks
  • 3 Open issues
  • 12 Versions
  • 14 % Grown

The README.md

Build Status Coverage Status Total Downloads Latest Stable Version Documentation Status Gratipay, (*1)

Version

A CakePHP 4.x plugin that facilitates versioned database entities, (*2)

Installation

Add the following lines to your application's composer.json:, (*3)

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

followed by the command:, (*4)

composer update, (*5)

Or run the following command directly without changing your composer.json:, (*6)

composer require josegonzalez/cakephp-version:dev-master, (*7)

Usage

In your app's config/bootstrap.php add:, (*8)

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

Usage

Run the following schema migration:, (*9)

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;

Note that the content field must be nullable if you want to be able to version any nullable fields in your application., (*10)

You may optionally add a version_id field of type integer to the table which is being versioned. This will store the latest version number of a given page., (*11)

If you wish to create the table using cakephp/migrations then you will need to use a migration that looks something like this:, (*12)

<?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();
    }
}

Add the following line to your entities:, (*13)

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

And then include the trait in the entity class:, (*14)

class PostEntity extends Entity {
    use VersionTrait;
}

Attach the behavior in the models you want with:, (*15)

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

Whenever an entity is persisted - whether via insert or update - that entity is also persisted to the version table. You can access a given revision by executing the following code:, (*16)

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

You can optionally retrieve all the versions:, (*17)

$versions = $entity->versions();

Storing Additional Meta Data

cakephp-version dispatches an event Model.Version.beforeSave which you can optionally handle to attach additional meta-data about the version., (*18)

Add the necessary additional fields to your migration, for example:, (*19)

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;

Then define an event listener to handle the event and pass in additional metadata, for example:, (*20)

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'
        ];
    }
}

Your event listener can then be attached in your project, for example:, (*21)

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

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

Note that handling this event also allows you to modify/overwrite values generated by the plugin. This can provide useful functionality, but ensure that if your event listener returns array keys called version_id, model, foreign_key, field, content or created that this is the intended behavior., (*22)

Storing user_id as Meta Data

To store the user_id as additional meta data is easiest in combination with Muffin/Footprint. The above insertAdditionalData() method could then look like this:, (*23)

    /**
     * @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;
    }

Any controller with the FootprintAwareTrait used will then provide the _footprint data into the model layer for this event callback to use., (*24)

Bake Integration

If you load the plugin using 'bootstrap' => true, this plugin can be used to autodetect usage via the properly named database table. To do so, simply create a table with the version schema above named after the table you'd like to revision plus the suffix _versions. For instance, to version the following table:, (*25)

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 the following table:, (*26)

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;

You can create a migration for this with the following bake command:, (*27)

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

You'll also want to set the content field in this migration to nullable, otherwise you won't be able to version fields that can be nulled., (*28)

To track the current version in the posts table, you can create a migration to add the version_id field to the table:, (*29)

bin/cake bake migration add_version_id_to_posts version_id:integer

Configuration

There are five behavior configurations that may be used:, (*30)

  • versionTable: (Default: version) The name of the table to be used to store versioned data. It may be useful to use a different table when versioning multiple types of entities.
  • versionField: (Default: version_id) The name of the field in the versioned table that will store the current version. If missing, the plugin will continue to work as normal.
  • additionalVersionFields: (Default ['created']) The additional or custom fields of the versioned table to be exposed as well. By default prefixed with version_, e.g. 'version_user_id' for 'user_id'.
  • referenceName: (Default: db table name) Discriminator used to identify records in the version table.
  • onlyDirty: (Default: false) Set to true to version only dirty properties.

The Versions

09/07 2018

dev-master

9999999-dev https://github.com/josegonzalez/cakephp-version

CakePHP ORM behavior to allow versioning of records

  Sources   Download

MIT

The Requires

 

The Development Requires

orm cakephp version revision

09/07 2018

2.1

2.1.0.0 https://github.com/josegonzalez/cakephp-version

CakePHP ORM behavior to allow versioning of records

  Sources   Download

MIT

The Requires

 

The Development Requires

orm cakephp version revision

25/04 2018

2.0

2.0.0.0 https://github.com/josegonzalez/cakephp-version

CakePHP ORM behavior to allow versioning of records

  Sources   Download

MIT

The Requires

 

The Development Requires

orm cakephp version revision

20/04 2017

1.7.0

1.7.0.0 https://github.com/josegonzalez/cakephp-version

CakePHP ORM behavior to allow versioning of records

  Sources   Download

MIT

The Requires

 

The Development Requires

orm cakephp version revision

27/03 2017

1.6.0

1.6.0.0 https://github.com/josegonzalez/cakephp-version

CakePHP ORM behavior to allow versioning of records

  Sources   Download

MIT

The Requires

 

The Development Requires

orm cakephp version revision

29/11 2016

1.5.0

1.5.0.0 https://github.com/josegonzalez/cakephp-version

CakePHP ORM behavior to allow versioning of records

  Sources   Download

MIT

The Requires

 

The Development Requires

orm cakephp version revision

19/09 2016

1.4.0

1.4.0.0 https://github.com/josegonzalez/cakephp-version

CakePHP ORM behavior to allow versioning of records

  Sources   Download

MIT

The Requires

 

The Development Requires

orm cakephp version revision

24/03 2016

1.3.0

1.3.0.0 https://github.com/josegonzalez/cakephp-version

CakePHP ORM behavior to allow versioning of records

  Sources   Download

MIT

The Requires

 

The Development Requires

orm cakephp version revision

23/12 2015
02/12 2015
29/11 2015

1.1.0

1.1.0.0 https://github.com/josegonzalez/cakephp-version

CakePHP plugin to allow versioning of records

  Sources   Download

MIT

The Requires

 

The Development Requires

cakephp version revision

17/05 2015

1.0.0

1.0.0.0 https://github.com/josegonzalez/cakephp-version

CakePHP plugin to allow versioning of records

  Sources   Download

MIT

The Requires

 

The Development Requires

cakephp version revision