Reputation: 2924
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
?
Upvotes: 11
Views: 9950
Reputation: 184
You could use ->isDirty() in the entity to see if a field has been modified.
// Prior to 3.5 use dirty()
$article->isDirty('title');
check the doc: https://book.cakephp.org/3/en/orm/entities.html#checking-if-an-entity-has-been-modified
Upvotes: 1
Reputation: 8919
With reference to Alexander Morland Answer.
How about this instead of looping through it in before filter.
$result = array_diff_assoc($this->old[$this->alias],$this->data[$this->alias]);
You will get key as well as value also.
Upvotes: 8
Reputation: 6434
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[$this->alias][$key] != $value) {
$changed_fields[] = $key;
}
}
}
// $changed_fields is an array of fields that changed
return true;
}
Upvotes: 18
Reputation: 11
You can call getAffectedRows() on any model class.
From class Model :
/**
* Returns the number of rows affected by the last query
*
* @return int Number of rows
* @access public
*/
function getAffectedRows() {
$db =& ConnectionManager::getDataSource($this->useDbConfig);
return $db->lastAffected();
}
Upvotes: -1
Reputation: 4203
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')));
Upvotes: 0
Reputation: 4203
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.
Upvotes: 0
Reputation: 22408
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.
Upvotes: -1