Reputation: 2104
I'm creating an audit trail module that i will put in a larger system; and i've created a table to store the trail entries , as an "auditor" what i want to see the currently logged on user, the page where he/she is in, what action he/she did, and what were the changes and when...
these are basically what i want to see; my audit trail table looks like:
User| Timestamp| Module Name| Action| Old Value| New Value| Description
i basically had no problem getting the user, by
Yii::app()->session['username'];
the page/module and action by getting the controller's :
$this->module->getName();
$this->action->id;
My problem lies with the changes old value to new value, the edits done by the user. i could sort of "sniff" out what edits/ changes he/she did by literally copying the variables and passing it through my function where i create the log.. How do i do this dynamically?
i sort of want to detect if a certain model's properties or attributes has been changed and see what changes were made so that i could get a detail log...Thanks ! sorry, i'm really trying hard to explain this.
Upvotes: 5
Views: 6754
Reputation: 529
Your solution is good, but what if there're 2 threads that call ->save() at the same time?
Assume that:
summary, there're 2 log: A->B, A->C. If this is not problem for you, just ignore it and do the above solution.
Upvotes: 0
Reputation: 6736
Quick example:
class Book extends CActiveRecord
{
private $oldAttrs = array();
public static function model($className = __CLASS__)
{
return parent::model($className);
}
public function tableName()
{
return 'book';
}
protected function afterSave()
{
// store history
if (!$this->isNewRecord) {
$newAttrs = $this->getAttributes();
$oldAttrs = $this->getOldAttributes();
// your code
}
return parent::afterSave();
}
protected function afterFind()
{
// Save old values
$this->setOldAttributes($this->getAttributes());
return parent::afterFind();
}
public function getOldAttributes()
{
return $this->oldAttrs;
}
public function setOldAttributes($attrs)
{
$this->oldAttrs = $attrs;
}
}
Upvotes: 6
Reputation: 8607
In each model that you want to observe you can write a afterFind()
method, where you store the current DB attributes into some private variable, e.b. _dbValues
. Then in beforeSave()
you verify the current attributes with the ones in _dbValues
and create an audit record if there was a change.
After you have this working, you can take it a step further and create a behavior from it. You'd put the private variable, the afterFind()
and the beforeSave()
method there. Then you can attach that behavior to many records.
Upvotes: 8