Hide
on 19/9/07

You may well find that you want to automatically know which user is adding or updating your database info. There are a few ways to do this and I recently, inadvertently, let slip that I have a whoDunnit (who did it) behavior which I use for exactly this purpose.

I wasn't sure if I should make it public; trouble is a little knowledge is a dangerous thing, and the technique used here could be (ab)used to bypass some of the structure and features that Cake brings to the developing-a-php-application table.

However, it is a very useful bit of code and for the benefit of anyone interested, the code is below:

  1. <?php
  2. class WhoDunnitBehavior extends ModelBehavior {
  3. function setup(&$model, $config = array()) {
  4. $this->settings[$model->name] = am (array('enabled' => true),$config);
  5. }
  6. function enableWhoDunnit(&$model, $enable = null) {
  7. if ($enable !== null) {
  8. $this->settings[$model->name]['enabled'] = $enable;
  9. }
  10. return $this->settings[$model->name]['enabled'];
  11. }
  12. function beforeSave(&$model) {
  13. extract ($this->settings[$model->name]);
  14. if (!$enabled) {
  15. return true;
  16. }
  17. $model->data[$model->name]['user_id'] = $_SESSION['User']['id'];
  18. return true;
  19. }
  20. }
  21. ?>

This version does one thing and one thing only: It populates the user_id field with the current logged in user's ID for any save. It can be bypassed, which an administrative user might need to do to be able to allocate data with another user in the system, simply by calling $this->Model->enableWhodunnit(false); any time before saving. I do have another version in the works which will generate a basic audit trail style log (User X logged in, User X updated Y SUCCESS, User X deleted Z FAIL, User X logged out), but that, if you are interested, will have to wait for another day and preferably a bribe :).

Wrapping Up

A behavior, which records exactly what it says on the tin.

Bake on!

6 Responses to Automatically track who makes Database changes

  1. 1

    One of my clients made us do this - there were two fields created_by and modified_by instead of just one and for a good measure it was coupled with what was called "soft delete"

    It served its purpose for the client but I would have preferred a nice generic logging behavior instead...

  2. 2

    Great! I will definitely be giving this a go, thanks for sharing.

  3. 3

    I also use the approach with created_by and modified_by. It's an easy way to get a quick overview about changes. And in most cases this is absolutely enough.

  4. 4

    This is my more comprehensive audit behavior that tracks both who made a change, when it was made and what the value was before the change was made.

    http://bin.cakephp.org/saved/23973

    For some reason it also tracks what the field became - cannot remember why!

    Anyway, it seems to work ok. Perhaps this code might be sufficient 'bribe' to hear about the new version in the works??

  5. 5

    Oooo I dunno. You might have to wait for me to finish it first :D. I have another behavior which does something similar to what you have shown and can be used for a complete audit trail (there's no need to log what changed, as each state of the object is in the database and can be compared); what I mentioned in the blog post was merely a log of events but the way it is/will be implemented is similar to what you ahve shown.

    Thanks for sharing!

  6. 6

    I did today a sort of changes tracking behavior. It uses altered model's table for storing the history of changes. Additionaly fields from related models may be saved with static_foreign_fields defined in config. There's also soft delete and a cleanup function. It's a bit dirty and lacks flexibility (only mysql supported, maybe pgsql), but it's my first attempt.

    http://cake.ima.pl/files/history_tracking.phps

    Greetings