We are moving our forum in GitHub Discussions. For questions about Phalcon v3/v4 you can visit here and for Phalcon v5 here.

Snapshot functionality in models, and update() method

I am overriding the built-in update() method in Phalcon\Mvc\Model in order to do audit logging. So if I have a MyModel, it extends ModelBase which extends Phalcon\Mvc\Model. In ModelBase:

  public function update($data=false, $whiteList=false){



    //acount for blank passed data array
      $data = $this->toArray();

    $preupdatedata = $this->getSnapshotData();

    //create a new audit transaction row
    $tr = new AuditTransaction();
    $ts = new \DateTime();

    $identity = $this->getDI()->get('auth')->getIdentity();

    //assignment of variables
    $tr->assign ( array(
            'schema_name' => 'dsmc',
            'table_name' => $this->table_name,
            'table_id' => $this->id,
            'timestamp' => $ts->format('Y-m-d H:i:s:u'),
            'ip_address' => $this->getIP(),
            'user_id' => $identity['id'], //change to real user ID once authentication implemented
            'action_type' => 'U' //update

    foreach($data as $col_name => $datum){
    $av = new AuditValues();
    $av->assign(array ( 
         'transaction_id' => $tr->id,
         'column_name' => $col_name,
         'new_value' => $datum,
         'old_value' => $preupdatedata[$col_name]));
    return $ret;

Since I am calling the update() on the second line, I assume that $this->getShapShotData() will contain the previous data values after the update occurs, is that correct? I am setting $this->keepSnapshots(true) in the ModelBase's initialize()...

If MyModel (which extends ModelBase) is using getters and setters, and I do setSomeField() does the value change immediately or only after an explicit call to update()? When I do currently in a controller:

$model = MyModel::findFirstById($someid);

I get "Data passed to update() must be an array"

Any ideas why?

Maybe instead of overriding update you can hook into afterUpdate? Instead of re-inventing the wheel I reccomend you look at a bit cleaner of a solution. Infact this post has several different ways to tackle it:


public function notify($eventType, $model)
    //Fires 'logAfterUpdate' if the event is 'afterUpdate'
    if ($eventType == 'afterUpdate') {
        return $this->auditAfterUpdate($model);


I saw that post after I had already written a lot of my stuff :( Also I need to audit VIEWS as well and I have a ton of code around that so I don't want to ditch what I have done already...

If I use afterUpdate() will the contents of getSnapShotData() contain the pre-update values?