9
mysql> select nid, uid, created, changed from node;
+-----+-----+------------+------------+
| nid | uid | created    | changed    |
+-----+-----+------------+------------+
|   1 |   8 | 1336040166 | 1336046390 |
+-----+-----+------------+------------+

I'd like to have an "changed by" column on the node table, exactly as we have a "created by" (the uid field). This would keep track of who made the last change on that node. I know that this could be derived from the node_revision table but this depends on the revisions being enabled for the content types I'm interested.

So, what is the best way to do this? And why doesn't Drupal core offer this by default? I thought that "changed by" is a pretty standard piece of information that a CMS should attach to content.

  • 2
    Is there a reason you can't enable revisioning? Seems like the easiest way to get what you need. It's probably what I'd do. If people are going to be editing nodes frequently, it also means you have a backup of previous versions. – Chapabu May 3 '12 at 13:41
  • Yes I can. I'd like to know if it's possible to have it on the main node table though. It looks more straightforward. – cherouvim May 3 '12 at 14:07
18
+50

I thought this would be quite tough to do, but as it turns out it's fairly easy.

You just need to create a custom module that adds a column to the node table on install, implement hook_schema_alter() so Drupal knows about the new column, and add some logic to provide a value before the node is saved.

Here's a small module that will do the trick:

File: node_table_alter.info

name = Node Table Alter
core = 7.x

File: node_table_alter.install

function node_table_alter_install() {
  // Add the new field to the node table
  $field = array(
    'description' => 'Stores the user id of the last user to alter the node',
    'type' => 'int',
    'unsigned' => TRUE
  );

  db_add_field('node', 'changed_by', $field);
}

File: node_table_alter.module

function node_table_alter_schema_alter(&$schema) {
  // Add the new field to the schema cache
  $schema['node']['fields']['changed_by'] = array(
    'description' => 'Stores the user id of the last user to alter the node',
    'type' => 'int',
    'unsigned' => TRUE
  );
}

function node_table_alter_node_presave($node) {
  // Populate the changed_by column with current user's id
  $node->changed_by = $GLOBALS['user']->uid;
}

You may want to add logic to remove the field again on uninstall, and add an index to the table for the changed_by column (see db_add_index()), but this should give you a good place to start.

The beauty of this method is that you have effectively added a new property to the node. You'll be able to use node_load(), EntityFieldQuerys, etc. with it as if it were any of the other standard properties for a node.

God bless Drupal for being so extendable!

  • BTW you can use exactly the same logic to answer your other question. – Clive May 7 '12 at 14:27
  • 2
    For complete entity integration, and if your are using the Entity API module, you will also need to implement hook_entity_property_info() to pvoide informatiom about this new property. – Pierre Buyle May 7 '12 at 14:39
  • @PierreBuyle Good point, didn't think of that – Clive May 7 '12 at 14:46
  • 1
    This is exactly what the UUID module does. Check it out for a more complete implementation of something similar. drupal.org/project/uuid – paul-m May 7 '12 at 18:21
  • Thanks a lot for the detailed explanation and clean solution! – cherouvim May 9 '12 at 10:00
1

I guess you could add a entity reference field (let's call it field_changed_by_user) to the content type you need to track. Then you could use hook_node_presave to save the user id to the node like this:

function hook_node_presave($node) {
  if ($node->nid && $node->type == 'content_type_to_track_changes_for') {
    global $user;
    $node->field_changed_by_user['und'][0]['target_id'] = $user->uid;
  }
}

I think it's also possible to update the field with the user's id just by creating a rule. You can read more here.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.