Implementing entity revisioning

Last updated on
15 March 2018

Drupal 7 will no longer be supported after January 5, 2025. Learn more and find resources for Drupal 7 sites

Entity revisioning is fairly simple - most of it is handled by field API, so you just need to implement a revision table, and appropriate load and save functions, and add an {example_revision} table with the appropriate columns.

hook_schema implementation

/**
 * Implements hook_schema().
 */
function example_schema() {
  $schema['example'] = array(
    'description' => 'Keeps track of example entities.',
    'fields' => array(
      'example_id' => array(
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'description' => 'Unique example id.',
      ),
      'vid' => array(
        'description' => 'The current {example_revision}.vid version identifier.',
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'created' => array(
        'description' => 'The Unix timestamp when the example was created.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
      'changed' => array(
        'description' => 'The Unix timestamp when the example was most recently saved.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
      // .. Any other columns you need in for your entity
    ),
    'primary key' => array('example_id'),
  );
  $schema['example_revision'] = array(
    'description' => 'Keeps track of example entities.',
    'fields' => array(
      'example_id' => array(
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
        'description' => 'Unique example id (entity id).',
      ),
      'vid' => array(
        'description' => 'The current {example_revision}.vid version identifier.',
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'changed' => array(
        'description' => 'The Unix timestamp when the example was most recently saved.',
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
      ),
      // Any other columns that you have in the example entity table that you
      // want to store in revisions.
    ),
    'primary key' => array('vid'),
  );
}

Add a _save function

This assumes your entities being saved are stdClass objects, with an entity ID, a created date, and any other data that you want to push into the database. New entities to be saved should also have a property called "is_new" set to TRUE.

function example_save($example) {
  if ($example->is_new) {
    // Adds the data to the entity table, and returns the new $example_id:
    $example_id = db_insert('example')
      ->useDefaults(array('example_id'))
      ->fields(array(
        'created'   => REQUEST_TIME,
        'changed'   => REQUEST_TIME,
        // Any other DB columns that you want to provide defaults for.
        ))
      ->execute();
    // Add the new entity ID back into the entity object
    $example->example_id = $example_id;
    // Add a revision for all new nodes.
    $example->revision = TRUE;
  }
  if (!empty($example->revision)) {
    // Add the entity data to the revision table, and return the unique revision id.
    $vid = db_insert('example_revision')
      ->useDefaults(array('vid'))
      ->fields(array(
        'example_id' => $example->example_id,
        // We don't need to store the creation time
        'changed'     => REQUEST_TIME,
        // Any other DB columns that you want to store, and for which you
        // need revisioning.
        ))
      ->execute();
      // Add the revision ID back to the entity
      $example->vid = $vid;
      
    // Update the revision ID on the entity table. 
    db_update('example')
      ->condition('example_id', $example->example_id)
      ->fields(array(
        'vid'     => $example->vid,
        ))
      ->execute();
  }
  
  // let Field UI deal with the fields.
  if ($example->is_new) {
    field_attach_insert('example', $example);
  }
  else {
    field_attach_update('example', $example);
  }
      
  return $example->example_id;
}

Help improve this page

Page status: No known problems

You can: