LogableBehavior

by alkemann
This behavior is created to be a plug-and-play database changes log that will work out of the box as using the created and modified fields does in cake core. It is NOT version control, undo or meant to be used as part of the public application. It's intent is to easily let you (the developer) log users activities that relates to database modifications (ie, add, edit and delete). If you just want to see what your users are doing or need to be able to say "That is not a bug, I can see from my log that you deleted the post yesterday." and don't want to spend more time that it takes to do "var $actsAs = array('Logable');" then this behavior is for you.

What

The intent of this behavior is to create a row in a log table every time a model's data (or all the model that the behavior is applied to) is created, edited or deleted. The developer can set this log table up to include as much detail as is required, and that is all the configuration that is needed.


How

Requirements

  • The behavior found on page 2
  • A Log model( empty but for a order variable [created DESC]
  • A "logs" table with these fields required :
    • id (int)
    • title (string) automagically filled with the display field of the model that was modified.
    • created (date/datetime) filled by cake in normal way
  • actsAs = array("Logable"); on models that should be logged

Optional configurations

Optional extra table fields for the "logs" table


  • description (string) Fill with a descriptive text of what, who and to which model/row
    • Example :Contact "John Smith"(34) added by User "Administrator"(1).

or if u want more detail, add any combination of the following


  • model (string) automagically filled with the class name of the model that generated the activity.
  • model_id (int) automagically filled with the primary key of the model that was modified.
  • action (string) automagically filled with what action is made (add/edit/delete)
  • user_id (int) populated with the supplied user info. (May be renamed. See bellow.)
  • change (string) depending on setting either
    • full: [name (alek) => (Alek), age (28) => (29)] or list: [name, age]
  • version_id (int) cooperates with VersionBehavior to link the the shadow table (thus linking to old data)

NB! VersionBehavior cooperation not implemented this version.


Optionally register what user was responisble for the activity

Supply configuration only if defaults are wrong. Example given with defaults:

Model Class:

<?php 
class Apple extends AppModel {
    var 
$name 'Apple';
    var 
$actsAs = array('Logable' => array(
        
'userModel' => 'User'
        
'userKey' => 'user_id'
        
'change' => 'list'// options are 'list' or 'full'
        
'description_ids' => TRUE // options are TRUE or FALSE
    
));
 [..]
?>

The change fields modifies what will be automagic filled in the change field if the log table has it. The description_ids option sets whether the description field will include the ids of the mode and the user. (See example above)


Usage


If you are using the user feature of the behavior, the models needs to know the id of the active user. This is most easily set in app controller in this way, but note that you may use the Logable::setUserData() method manually should you so desire.


Controller Class:

<?php 
// In AppController (or single controller if only needed once) add these lines to beforeFilter : 

if (sizeof($this->uses) && $this->{$this->modelClass}->Behaviors->attached('Logable')) {
    
$this->{$this->modelClass}->setUserData($this->activeUser);
}
?>

Where "$activeUser" should be an array in the standard format for the User model used :[/]

<? $activeUser = array( $UserModel->alias => array( $UserModel->primaryKey => 123$UserModel->displayField => 'Alexander')); ?>

any other key is just ignored by this behaviour.


Get the logs out


I don't supply a helper or views for this, I am sure you can manage, but I suggest you make one view and use the controllers viewpath or the controllers render method to only render a single view for all models that use the behavior.


To extract the logs, no matter of you want all events, or just for one model or one user, or even one user's activity on one model, you can ask any model that the behavior is enabled on. There are two methods


  • findLog($params)
  • findUserActions($user_id, $params)

You can off course query the Log model in the normal way.


findLog

This is the main function for retrieving the logged activities. It will by default (when called with no parameters) return all activities for the model it is called from, but it can also be used for any or all models from any model. The available options are listed bellow.


  • model (string)
  • action (string) (add/edit/delte) defaults to NULL (ie. all)
  • fields (array)
  • order (string) defaults to 'created DESC'
  • conditions (array) add custom conditions
  • model_id (int) ForeignKey for a single instance of logged model
  • user_id (int) defaults to NULL (all users).

Remember to user your own foreignKey if you did not use 'user_id'


<?php // examples
 // All acitivities on current model
 
$data $this->Apple->findLog();
 
// All acitivities on current model instance
 
$data $this->Apple->findLog('model_id'=>32);
 
// I am in apple controller, but i want acitivities for the user on a specific Logo isntance
 
$data $this->Apple->findLog(array('user_id'=>66,'model'=>'Logo','model_id'=>123));
?>

findUserActions

The first parameter is compulsory and is the ID of the user (foreignKey). The second is an array of options. The available options are listed bellow. Model and fields does the expected things, while events will create a description on the fly. This function is intended to be improved in the next version to be translatable / customizable.

  • model (string)
  • [li]events (boolean)
  • [li]fields (array)

<?php // examples
    // note we are asking for a different model
 
$data $this->User->findUserActions(301,array('model' => 'BookTest')); 
 
$data $this->Apple->findUserActions(301,array('events' => true));
 
$data $this->Model->findUserActions(301,array('fields' => array('id','model'),'model' => 'BookTest');
?>

The code (or download link) can be found on the next page.



You can download the newest version, including tests, here :

http://code.google.com/p/alkemann/downloads/list

[p]Or you can grab version 1.3 here

Behavior Class:

<?php 
/**
 * Logs saves and deletes of any model
 * 
 * Requires the following to work as intended :
 * 
 * - "Log" model ( empty but for a order variable [created DESC]
 * - "logs" table with these fields required :
 *     - id            [int]            : 
 *     - title         [string]         : automagically filled with the display field of the model that was modified.
 *        - created    [date/datetime] : filled by cake in normal way
 * 
 * - actsAs = array("Logable"); on models that should be logged
 * 
 * Optional extra table fields for the "logs" table :
 * 
 * - "description"     [string] : Fill with a descriptive text of what, who and to which model/row :  
 *                                 "Contact "John Smith"(34) added by User "Administrator"(1).
 * 
 * or if u want more detail, add any combination of the following :
 * 
 * - "model"        [string] : automagically filled with the class name of the model that generated the activity.
 * - "model_id"     [int]     : automagically filled with the primary key of the model that was modified.
 * - "action"       [string] : automagically filled with what action is made (add/edit/delete) 
 * - "user_id"      [int]    : populated with the supplied user info. (May be renamed. See bellow.)
 * - "change"       [string] : depending on setting either : 
 *                             [name (alek) => (Alek), age (28) => (29)] or [name, age]
 * 
 * - "version_id"    [int]     : cooperates with VersionBehavior to link the the shadow table (thus linking to old data)
 * @todo implement version cooperation
 * 
 * Optionally register what user was responisble for the activity :
 * 
 * - Supply configuration only if defaults are wrong. Example given with defaults :
 * 
 * class Apple extends AppModel {
 *         var $name = 'Apple';
 *         var $actsAs = array('Logable' => array('userModel' => 'User', 'userKey' => 'user_id'));
 *  [..]
 * 
 * - In AppController (or single controller if only needed once) add these lines to beforeFilter : 
 * 
 *       if (sizeof($this->uses) && $this->{$this->modelClass}->Behaviors->attached('Logable')) {
 *            $this->{$this->modelClass}->setUserData($this->activeUser);
 *        }
 *
 *   Where "$activeUser" should be an array in the standard format for the User model used :
 * 
 *   $activeUser = array( $UserModel->alias => array( $UserModel->primaryKey => 123, $UserModel->displayField => 'Alexander'));
 *   // any other key is just ignored by this behaviour.
 * 
 * @author Alexander Morland (alexander#maritimecolours.no)
 * @co-author Eskil Mjelva Saatvedt
 * @co-author Ronny Vindenes
 * @co-author Carl Erik Fyllingen
 * @category Behavior
 * @version 1.3
 */

class LogableBehavior extends ModelBehavior 
{
    var 
$user NULL;
    var 
$UserModel FALSE;
    
    
/**
     * Cake called intializer
     * Config options are :
     *    userModel         : 'User'. Class name of the user model you want to use (User by default), if you want to save User in log
     *    userKey           : 'user_id'. The field for saving the user to (user_id by default).
     *       change            : 'list' > [name, age]. Set to 'full' for [name (alek) => (Alek), age (28) => (29)]
     *       description_ids     : TRUE. Set to FALSE to not include model id and user id in the title field
     *
     * @param Object $Model
     * @param array $config
     */
    
function setup(&$Model$config null) {
        
$this->settings = array(
            
'userModel' => 'User',
            
'userKey' => 'user_id',
            
'change' => 'list',
            
'description_ids' => TRUE
        
);
        if (
$config) {
            
$this->settings array_merge($this->settings$config);
        }
                
        
App::import('model','Log');
        
$this->Log = new Log();
        if (
$this->settings['userModel'] != $Model->alias) {
            if (
App::import('model',$this->settings['userModel'])) {
                
$this->UserModel = new $this->settings['userModel']();
            }
        } else {
            
$this->UserModel $Model;
        }
       
    }
    
    function 
settings(&$Model) {
        return 
$this->settings;
    }
    
/**
     * Useful for getting logs for a model, takes params to narrow find. 
     * This method can actually also be used to find logs for all models or
     * even another model. Using no params will return all activities for
     * the models it is called from.
     *
     * Possible params :
     * 'model'         : mixed  (NULL) String with className, NULL to get current or FALSE to get everything
     * 'action'     : string (NULL) String with action (add/edit/delete), NULL gets all
     * 'order'         : string ('created DESC') String with custom order
     * 'conditions  : array  (array()) Add custom conditions
     * 'model_id'    : int     (NULL) Add a int 
     * 
     * (remember to use your own user key if you're not using 'user_id')
     * 'user_id'     : int      (NULL) Defaults to all users, supply id if you want for only one User
     * 
     * @param Object $Model
     * @param array $params
     * @return array
     */
    
function findLog(&$Model$params = array()) {
        
$defaults = array(
             
'model' => NULL,
             
'action' => NULL,
             
'order' => 'created DESC',
             
$this->settings['userKey'] => NULL,
             
'conditions' => array(),
             
'model_id' => NULL,
             
'fields' => array(),
        );
        
$params array_merge($defaults$params);
        
$options = array('order' => $params['order'], 'conditions' => $params['conditions'], 'fields' => $params['fields']);
        if (
$params['model'] === NULL) {
            
$params['model'] = $Model->alias;
        }
        if (
$params['model']) {
            if (isset(
$this->Log->_schema['model'])) {
                
$options['conditions']['model'] = $params['model'];
            } elseif (isset(
$this->Log->_schema['description'])) {            
                
$options['conditions']['description LIKE '] = $params['model'].'%';
            } else {
                return 
FALSE;
            }
        }
        if (
$params['action'] && isset($this->Log->_schema['action'])) {
            
$options['conditions']['action'] = $params['action'];
        }         
        if (
$params$this->settings['userKey'] ] && $this->UserModel && is_numeric($params$this->settings['userKey'] ])) {
            
$options['conditions'][$this->settings['userKey']] = $params$this->settings['userKey'] ];
        }
        if (
$params['model_id'] && is_numeric($params['model_id'])) {
            
$options['conditions']['model_id'] = $params['model_id'];
        }
        return 
$this->Log->find('all',$options);
    }
    
    
/**
     * Get list of actions for one user.
     * Params for getting (one line) activity descriptions 
     * and/or for just one model 
     *
     * @example $this->Model->findUserActions(301,array('model' => 'BookTest'));
     * @example $this->Model->findUserActions(301,array('events' => true));
     * @example $this->Model->findUserActions(301,array('fields' => array('id','model'),'model' => 'BookTest');
     * @param Object $Model
     * @param int $user_id
     * @param array $params
     * @return array
     */
    
function findUserActions(&$Model$user_id$params = array()) {
        if (!
$this->UserModel) {
            return 
NULL;
        }
        
// if logged in user is asking for her own log, use the data we allready have
        
if ( isset($this->user
             && isset(
$this->user[$this->UserModel->alias][$this->UserModel->primaryKey]) 
             && 
$user_id == $this->user[$this->UserModel->alias][$this->UserModel->primaryKey
             && isset(
$this->user[$this->UserModel->alias][$this->UserModel->displayField]) ) {
            
$username $this->user[$this->UserModel->alias][$this->UserModel->displayField];
        } else {
            
$this->UserModel->recursive = -1;
            
$user $this->UserModel->find(array($this->UserModel->primaryKey => $user_id));
            
$username $user[$this->UserModel->alias][$this->UserModel->displayField];
        }
        
$fields = array();
        if (isset(
$params['fields'])) {
            if (
is_array($params['fields'])) {
                
$fields $params['fields'];
            } else {
                
$fields = array($params['fields']);
            }
        }
        
$conditions = array($this->settings['userKey'] => $user_id);
        if (isset(
$params['model'])) {
            
$conditions['model'] = $params['model'];
        }
        
$data $this->Log->find('all', array(
            
'conditions' => $conditions,
            
'recursive' => -1,
            
'fields' => $fields
        
));
        if (! isset(
$params['events']) || (isset($params['events']) && $params['events'] == false)) {
            return 
$data;
        }
        
$result = array();
        foreach (
$data as $key => $row) {$one $row['Log'];
            
$result[$key]['Log']['id'] = $one['id'];
            
$result[$key]['Log']['event'] = $username;
            
// have all the detail models and change as list : 
            
if (isset($one['model']) && isset($one['action']) && isset($one['change']) && isset($one['model_id'])) {
                 if (
$one['action'] == 'edit') {
                     
$result[$key]['Log']['event'] .= ' edited '.$one['change'].' of '.low($one['model']).'(id '.$one['model_id'].')';
                     
//    ' at '.$one['created']; 
                 
} elseif ($one['action'] == 'add') {
                     
$result[$key]['Log']['event'] .= ' added a '.low($one['model']).'(id '.$one['model_id'].')';
                 } elseif (
$one['action'] == 'delete') {
                     
$result[$key]['Log']['event'] .= ' deleted the '.low($one['model']).'(id '.$one['model_id'].')';
                 }
                         
            } elseif ( isset(
$one['model']) && isset($one['action'])  && isset($one['model_id']) ) { // have model,model_id and action
                 
if ($one['action'] == 'edit') {
                     
$result[$key]['Log']['event'] .= ' edited '.low($one['model']).'(id '.$one['model_id'].')';
                     
//    ' at '.$one['created']; 
                 
} elseif ($one['action'] == 'add') {
                     
$result[$key]['Log']['event'] .= ' added a '.low($one['model']).'(id '.$one['model_id'].')';
                 } elseif (
$one['action'] == 'delete') {
                     
$result[$key]['Log']['event'] .= ' deleted the '.low($one['model']).'(id '.$one['model_id'].')';
                 }
            } else { 
// only description field exist
                
$result[$key]['Log']['event'] = $one['description'];
            }
                
        }
        return 
$result;
    }
    
/**
     * Use this to supply a model with the data of the logged in User.
     * Intended to be called in AppController::beforeFilter like this :
     *   
      *       if ($this->{$this->modelClass}->Behaviors->attached('Logable')) {
      *            $this->{$this->modelClass}->setUserData($activeUser);/
      *        }
     *
     * The $userData array is expected to look like the result of a 
     * User::find(array('id'=>123));
     * 
     * @param Object $Model
     * @param array $userData
     */
    
function setUserData(&$Model$userData null) {
        if (
$userData) {
            
$this->user $userData;
        }
    }
    
    function 
clearUserData(&$Model) {
        
$this->user NULL;
    }
    
    function 
beforeDelete(&$Model) {
        
$Model->recursive = -1;
        
$Model->read();
    }
    
    function 
afterDelete(&$Model) {
        
$logData = array();
         if (isset(
$this->Log->_schema['description'])) {
             
$logData['Log']['description'] = $Model->alias;
             if (isset(
$Model->data[$Model->alias][$Model->displayField]) && $Model->displayField != $Model->primaryKey) {
                 
$logData['Log']['description'] .= ' "'.$Model->data[$Model->alias][$Model->displayField].'"';
             }
            if (
$this->settings['description_ids']) {
                
$logData['Log']['description'] .= ' ('.$Model->id.') ';
            }
            
$logData['Log']['description'] .= __('deleted',TRUE);
         }        
        
$logData['Log']['action'] = 'delete';     
        
$this->_saveLog($Model$logData);
    }
    
    function 
beforeSave(&$Model) {
        if (isset(
$this->Log->_schema['change']) && $Model->id) {
            
$Model->recursive = -1;
            
$this->old $Model->find(array($Model->primaryKey => $Model->id));
        }
    }
    
    function 
afterSave(&$Model,$created) {
         if (
$Model->id) {
            
$id $Model->id;
        } elseif (
$Model->insertId) {
            
$id $Model->insertId;
        }         
        if (isset(
$this->Log->_schema['model_id'])) {
               
$logData['Log']['model_id'] = $id;
        }
        if (isset(
$this->Log->_schema['description'])) {        
            
$logData['Log']['description'] = $Model->alias;
             if (isset(
$Model->data[$Model->alias][$Model->displayField]) && $Model->displayField != $Model->primaryKey) {
                 
$logData['Log']['description'] .= ' "'.$Model->data[$Model->alias][$Model->displayField].'"';
             }
            
            if (
$this->settings['description_ids']) {
                
$logData['Log']['description'] .= ' ('.$id.') ';
            }
                                        
            if (
$created) {
                
$logData['Log']['description'] .= __('added',TRUE);
            } else {
                
$logData['Log']['description'] .= __('updated',TRUE);   
            }  
        }     
        if (isset(
$this->Log->_schema['action'])) {                    
            if (
$created) {
                
$logData['Log']['action'] = 'add';
            } else { 
                
$logData['Log']['action'] = 'edit';         
            }  
            
        }

        if (isset(
$this->Log->_schema['change'])) {
            
$logData['Log']['change'] = '';
            foreach (
$Model->data[$Model->alias] as $key => $value) {
                if (isset(
$Model->data[$Model->alias][$Model->primaryKey]) && !empty($this->old)) {
                    
$old $this->old[$Model->alias][$key];
                } else {
                    
$old '';
                }
                if (
$key != 'modified' && $value != $old) {
                    if (
$this->settings['change'] == 'full') {
                        
$logData['Log']['change'] .= $key ' ('.$old.') => ('.$value.'), ';
                    } else {
                        
$logData['Log']['change'] .= $key ', ';    
                    }                    
                }
            }
            if (
strlen($logData['Log']['change'])) {
                
$logData['Log']['change'] = substr($logData['Log']['change'],0,-2);
            } else {
                return 
true;
            }            
        }  
        
$this->_saveLog($Model$logData);
    }
    
    
/**
     * Does the actual saving of the Log model. Also adds the special field if possible.
     * 
     * If model field in table, add the Model->alias
     * If action field is NOT in table, remove it from dataset
     * If the userKey field in table, add it to dataset
     * If userData is supplied to model, add it to the title 
     *
     * @param Object $Model
     * @param array $logData
     */
    
function _saveLog(&$Model$logData) {  
         if (isset(
$Model->data[$Model->alias][$Model->displayField]) && $Model->displayField != $Model->primaryKey) {
             
$logData['Log']['title'] = $Model->data[$Model->alias][$Model->displayField];
         } else {
             if (
$Model->id) {
                 
$id $Model->id;
             } elseif (isset(
$Model->data[$Model->alias][$Model->primaryKey])) {
                 
$id $Model->data[$Model->alias][$Model->primaryKey];
             } else {
                 
$id 'MISSING';
             }
             
$logData['Log']['title'] = $Model->alias.' ('.$id.')';
         }
        
        if (isset(
$this->Log->_schema['model'])) {
            
$logData['Log']['model'] = $Model->alias;
        }
        
        if (isset(
$this->Log->_schema['model_id'])) {
            if (
$Model->id) {
                
$logData['Log']['model_id'] = $Model->id;
            } elseif (
$Model->insertId) {
                
$logData['Log']['model_id'] = $Model->insertId;
            }             
        }
        
        if (!isset(
$this->Log->_schema'action' ])) {
            unset(
$logData['Log']['action']);
        }
        
        if (isset(
$this->Log->_schema$this->settings['userKey'] ]) && $this->user) {
            
$logData['Log'][$this->settings['userKey']] = $this->user[$this->UserModel->alias][$this->UserModel->primaryKey];
        }      
        
        if (isset(
$this->Log->_schema['description'])) {
            if (
$this->user && $this->UserModel) {
                
$logData['Log']['description'] .= ' by '.$this->settings['userModel'].' "'.
                        
$this->user[$this->UserModel->alias][$this->UserModel->displayField].'"';
                if (
$this->settings['description_ids']) {
                    
$logData['Log']['description'] .= ' ('.$this->user[$this->UserModel->alias][$this->UserModel->primaryKey].')';
                }
                                            
            } else { 
                
// UserModel is active, but the data hasnt been set. Assume system action.
                
$logData['Log']['description'] .= ' by System';
            }
            
$logData['Log']['description'] .= '.';            
        }     
              
        
$this->Log->create($logData);
        
$this->Log->save(NULL,FALSE);        
    }
}
?>

1 | 2

Report

More on Behaviors

Advertising

Comments

  • tomas_maly posted on 05/04/11 05:41:01 PM
    the field 'change' should be 'changed', as 'change' is a reserved keyword in mysql. It won't let me create my 'logs' table otherwise.
  • luisgabriel84 posted on 04/23/11 12:26:44 AM
    Thanks to you I will finally catch the clown that keeps modifying records from my db..
  • Moorer posted on 08/26/10 02:11:19 PM
    first i think is unnecessary have __('added', true); (delete, updated...) in logable.php behavior, because if you put your app in spanish, or other lenguaje in the description you save the value in that lenguaje, example mi app is in spanish and english, and when i put mi app in spanish have a half description in spanish, and if i use mi app in english, i have all description in english but, when i change app to spanish i see description in english, and not in spanish..

    i think a good resolved to this problem is the next idea.

    put this in log.php model..
    private function __registerGetText(){
    __('by',true);
    __('System',true);
    __('System.',true);
    __('add',true);
    __('edit',true);
    __('added',true);
    __('updated',true);
    __('delete',true);
    __('deleted',true);
    }

    and in the views of logs.. use this

     
     
     
     
     
     
     
    and the must beauty is you get free translate to model name
    you can do the same whit title, action, and if you do some modification to this

    foreach (explode(',', $data['Log']['change']) as $change) {
    preg_match('/(\w+?) \((\w*?)\) => \((\w+?)\)/', $change, $matches);
    list($search, $field, $from, $to) = $matches;
    print "change \"$field\" from \"$from\" to \"$to\"\n";
    }

    you can get a full translate for your lenguaje for this nice behavior..

    sorry mi english suck when is write :P
  • annapurna posted on 06/03/10 09:26:49 AM
    Hello,
    thanks a lot for this behavior, exactly what I needed !

    I just came through an issue on an -old- server, with PHP 4.1 :

    Missing argument 1 for log() [...] cake/libs/object.php on line 150

    I think it's because of PHP4 letter case problem. As there is already a log() function in cake core, it calls it on line 95 :
    $this->Log = new Log();

    So, for anyone who have this problem, just rename the Log model and its table as you wish, without forgot each occurency in logableBehavior!
  • PopeFelix posted on 03/02/10 01:53:41 PM
    How is that hard?

    Your change is going to look like "some_field (some_value) => (some_new_value), some_field2 (some_value2) => (some_new_value2)".


    foreach (explode(',', $data['Log']['change']) as $change) {
        preg_match('/(\w+?) \((\w*?)\) => \((\w+?)\)/', $change, $matches);
        list($search, $field, $from, $to) = $matches;
        print "change \"$field\" from \"$from\" to \"$to\"\n";
    }

    Yes, it requires knowing a little bit of PCRE, but PCRE is a massively useful tool.
    • emadnajeeb posted on 03/02/10 07:54:43 PM
      How is that hard?

      Your change is going to look like "some_field (some_value) => (some_new_value), some_field2 (some_value2) => (some_new_value2)".


      foreach (explode(',', $data['Log']['change']) as $change) {
          preg_match('/(\w+?) \((\w*?)\) => \((\w+?)\)/', $change, $matches);
          list($search, $field, $from, $to) = $matches;
          print "change \"$field\" from \"$from\" to \"$to\"\n";
      }

      Yes, it requires knowing a little bit of PCRE, but PCRE is a massively useful tool.

      @Kit: Thanks. Another reason for doing this is if you have commas(,) in your content.

  • emadnajeeb posted on 03/02/10 12:14:03 PM

    I found it hard to parse change log field for presentation and modified line 392 to

    $changed_fields[$key] = array('from' => $old,'to'=>$value);

    and line 402 to

    $logData['Log']['change'] = serialize($changed_fields);
  • PopeFelix posted on 11/25/09 02:20:24 PM
    If you're getting segfaults with this behavior, make sure you've got the latest version from github: http://github.com/alkemann/CakePHP-Assets/blob/master/models/behaviors/logable.php
  • lucasrcosta posted on 08/20/09 12:19:54 PM
    Hi, congratulations.

    Is there anyway that this would also work with HasAndBelongsToMany Relashionship Tables?

    I mean if a post HasAndBelongsToMany tags, it would Log when adding tags to a post.

    I tried modelizing the table and then putting the behavior but it didn't work. I don't know if it is possible for these kinds of tables to trigger the callbacks.

    Regards to all...
  • alscheuring posted on 07/24/09 08:20:41 AM
    This works great, however with certain apps I already have a 'title' field for 'Mr., Mrs. Dr. etc'. What happens is that I end up with 'Mr.' in my logs table instead of the modified model. Is there a way to fix this other than changing my code?
  • GreenMushroom posted on 06/11/09 12:43:14 PM
    I am having a bit of trouble retrieving User Data from beforeFilter... I use the DarkAuth component to manage the Authentication as seen here :(http://bakery.cakephp.org/articles/view/darkauth-another-way). And I usually retrieve user data like so: $this->DarkAuth->current_user['User']. which is unavailable in the before filter function. Is there another way to pass UserData to the behavior?

    Fixed:

    $this->DarkAuth->getUserInfo()
  • jstein posted on 05/09/09 05:32:52 AM
    Great work!

    I had some troubles figuring out what I should pass to setUserData in beforeFilter. These lines seems to do the job:
        if (sizeof($this->uses) && $this->{$this->modelClass}->Behaviors->attached('Logable')) {
          $this->{$this->modelClass}->setUserData($this->Session->read('Auth'));
        }

    Regards

    Jonathan
  • Kumazatheef posted on 01/27/09 12:59:13 AM
    Great behaviour; however, running into an oddity ... getting a seg fault when I tried just having `$actsAs = array('Logable');` on the global AppModel. Still trying to track it down.
    Just curious why a new User is being instantiated on line 98 if we're passing it info in setUserData??
    • BlueC posted on 04/28/09 08:27:41 AM
      Great behaviour; however, running into an oddity ... getting a seg fault when I tried just having `$actsAs = array('Logable');` on the global AppModel. Still trying to track it down.
      Same here. Anyone got a fix for this?
  • alkemann posted on 01/15/09 11:00:32 AM
    Logable has hit version 2, there has been some changes to the api, so i'll leave this code un-updated for now, but you can grab it from my google code at http://code.google.com/p/alkemann/downloads

    Where you can also download it's big brother, RevisionBehavior (that also just hit version 2) and it's cousin, MultilingualBehavior.
  • ignacio posted on 12/29/08 10:57:39 AM
    it works! I was going to built sth exactly like this, but not so fancy!.

    Are you still working on linking it to the Revision Behaviour? it would be really great.

    I´ll have a look and see what i can do with it.

    Thank you!

login to post a comment.