Changes
Title
unchanged
How to avoid a database update if the ActiveRecord was not modified
Category
unchanged
How-tos
Yii version
unchanged
Tags
unchanged
active record, database
Content
changed
[...]
{
if($this->getIsNewRecord())
throw new CDbException(Yii::t('yii','The active record cannot be updated because it is new.'));
if($this->beforeSave())
{
if ($this->detectDirty && $this->_originalHash == $this->calculateHash(true)) {
$this->_isWritten = false;
if ($this->doAfterSaveIfNotDirty)[...]
/**
* Calculate a hash from the model's attributes.
* It excludes attributes in neverMakeDirtyAttributes.
* If $castEmpty=true it will typecast empty string values to null if the matching database field is not a string.
* That is what the Yii framework does when saving, so we need to mimic this here to be able to compare attributes after load and before save.
* See {@see CActiveRecord::createUpdateCommand}.
* @param boolean $castEmpty
* @return string
*/
private function calculateHash(
$castEmpty = false) {
$a = array_diff_key($this->getAttributes(
false), array_flip($this->neverMakeDirtyAttributes));
return md5(serialize($a))if ($castEmpty) {
$a = $this->typeCastEmpty($a);
}
return md5(serialize($a));
}
/**
* Any empty attributes (value==='') for non-string database fields are translated into null.
* @param array $a
* @return array
*/
private function typeCastEmpty($a) {
$table=null;
foreach($a as $k=>$v) {
if ($v==='') {
if ($table===null)
$table=$this->getTableSchema();
$column = $table->getColumn($k);
if($column->allowNull && $column->type!=='string')
$a[$k]=null;
}
}
return $a;
}
}
```[...]