tags:

views:

1007

answers:

4

I'm using the cacheCounter in CakePHP, which increments a counter for related fields.

Example, I have a Person table a Source table. Person.source_id maps to a row in the Source table. Each person has one Source, and each Source has none or many Person rows.

cacheCounter is working great when I change the value of a source on a person. It increments Source.Person_Count. Cool.

But when it increments, it adds it to the destination source for a person, but doesn't remove it from the old value. I tried updateCacheControl() in afterSave, but that didn't do anything.

So then I wrote some code in my model for afterSave that would subtract the source source_id, but it always did this even when I wasn't even changing the source_id. (So the count went negative).

My question: Is there a way to tell if a field was changed in the model in CakePHP?

A: 

See if the "save" uses some sort of DBAL call that returns "affected rows", usually this is how you can judge if the last query changed data, or if it didn't. Because if it didn't, the affected rows after an UPDATE-statement are 0.

Till
Thanks. I was actually thinking if the value changed from before the edit action to after the edit action, pre-save to sql.
Justin
I am not sure I understand, do you want to avoid the SQL call?
Till
A: 

Edits happen infrequently, so another select before you do the update is no big deal, so, fetch the record before you save, save it, compare the data submitted in the edit form with the data you fetched from the db before you saved it, if its different, do something.

neilcrookes
+1  A: 

In the edit view, include another hidden field for the field you want to monitor but suffix the field name with something like "_prev" and set the value to the current value of the field you want to monitor. Then in your controller's edit action, do something if the two fields are not equal. e.g.

echo $form->input('field_to_monitor');
echo $form->hidden('field_to_monitor_prev', array('value'=>$form->value('field_to_monitor')));
neilcrookes
this isnt a very secure way of doing things. anyone with firebug can change the values of the _prev fields. In my oppinion it better to compare with the actual database to check for changes. see my answer
Alexander Morland
+3  A: 

To monitor changes in a field, you can use this logic in your model with no changes elsewhere required:

function beforeSave() {
    $this->recursive = -1;
    $this->old = $this->find(array($this->primaryKey => $this->id));
    if ($this->old){
        $changed_fields = array();
        foreach ($this->data[$this->alias] as $key =>$value) {
            if ($this->old[$key] != $value) {
                $changed_fields[] = $key;
            }
        }
    }
    // $changed_fields is an array of fields that changed
    return true;
}
Alexander Morland