メモ:Doctrineのレコードオブジェクトでset〜を呼び出したときのダーティチェック
Doctrineで既存のレコードをインスタンス化して、そのオブジェクトのフィールドの値を変更して保存する場合、「値が何も変わっていなければ保存しない」というチェックが行われます。
このチェックは、Doctrine_Recordクラスの_setメソッド内で行われます。
<?php protected function _set($fieldName, $value, $load = true) { if (array_key_exists($fieldName, $this->_values)) { $this->_values[$fieldName] = $value; } else if (array_key_exists($fieldName, $this->_data)) { $type = $this->_table->getTypeOf($fieldName); if ($value instanceof Doctrine_Record) { $id = $value->getIncremented(); if ($id !== null && $type !== 'object') { $value = $id; } } if ($load) { $old = $this->get($fieldName, $load); } else { $old = $this->_data[$fieldName]; } if ($this->_isValueModified($type, $old, $value)) { if ($value === null) { $value = $this->_table->getDefaultValueOf($fieldName); } $this->_data[$fieldName] = $value; $this->_modified[] = $fieldName; $this->_oldValues[$fieldName] = $old; switch ($this->_state) { case Doctrine_Record::STATE_CLEAN: case Doctrine_Record::STATE_PROXY: $this->_state = Doctrine_Record::STATE_DIRTY; break; case Doctrine_Record::STATE_TCLEAN: $this->_state = Doctrine_Record::STATE_TDIRTY; break; } } } else { try { $this->coreSetRelated($fieldName, $value); } catch (Doctrine_Table_Exception $e) { $success = false; foreach ($this->_table->getFilters() as $filter) { try { $value = $filter->filterSet($this, $fieldName, $value); $success = true; } catch (Doctrine_Exception $e) {} } if ($success) { return $value; } else { throw $e; } } } return $this; }
_isValueModifiedで、フィールドに対して新しい値が以前の値と同一なのかどうかを判定し、異なっていれば変更済フラグの設定や、オブジェクトのステータスの変更などを行っています。
このステータスは、例えばオブジェクトの保存(save)の場合、実際にsaveメソッドの処理を行うDoctrine_Connection_UnitOfWorkクラスのsaveGraphメソッドにて使用されます。STATE_CLEANならば何もしない、というコードもこのメソッドにあります。