Magento Certified Developer GuideCategory: 4. DatabaseDescribe the load-and-save process for a regular entity
Manish Prakash Staff asked 5 years ago

Model Load Process
This the code for a model load process in class Mage_Core_Model_Abstract

    public function load($id, $field=null)
    {
        $this->_beforeLoad($id, $field);
        $this->_getResource()->load($this, $id, $field);
        $this->_afterLoad();
        $this->setOrigData();
        $this->_hasDataChanges = false;
        return $this;
    }

So the first thing that happens here is “_beforeLoad()”. This fires two events “model_load_before” and “‘$this->_eventPrefix.’_load_before”. $this->_eventPrefix is name setup for every model, by default its value is “core_abstract”.

Next we have load() on the resource model. Here the actual row is read from database and it gets set to the current object using the “setData()” function. Also if there are any “_serializableFields” defined, they automatically get “unserialized”

Next we the “_afterLoad()” function. This also fires two events “model_load_after” and “‘$this->_eventPrefix.’_load_after'”.

Then the function “setOrigData()” is called which basically marks the current data as original. This is mainly used for dirty checking (has data changed).

SerializableFields are defined via _serializableFields in the model. This is very useful if you have complex data structure like array in the model and need to save it in a single column.

Model Save Process
The code for saving a model is more complicated than loading, it has the concept of transactions as well which we wont discuss right now.

The save process is also divided into 3 parts, “_beforeSave()” , “$this->getResource()->save()” and “_afterSave()”
Before Save event fires the events “model_save_before” and “‘$this->_eventPrefix.’_save_before'” event, similarly “_afterSave()”

The resource save() function first serializes the fields which are marked to be serialized. Next there is check for uniqueFields, if we set any unique fields in the model it checks so that we don’t save any duplicate data.
Next if check if we have set “id” in the model using “$this->getId()”. If “id” is defined it fires an update query else it does a insert. In the end it unserializes the serialized field above. Also its important to that data is inserted only if the column name in database and field name of the object match, else it wont insert that data.

TIP: You can defined unique fields for your module by fields in array “_uniqueFields” and serialized fields using array “_serializableFields”.

Below is the entire code for save()

public function save(Mage_Core_Model_Abstract $object)
    {
        if ($object->isDeleted()) {
            return $this->delete($object);
        }

        $this->_serializeFields($object);
        $this->_beforeSave($object);
        $this->_checkUnique($object);
        if (!is_null($object->getId()) && (!$this->_useIsObjectNew || !$object->isObjectNew())) {
            $condition = $this->_getWriteAdapter()->quoteInto($this->getIdFieldName().'=?', $object->getId());
            /**
             * Not auto increment primary key support
             */
            if ($this->_isPkAutoIncrement) {
                $data = $this->_prepareDataForSave($object);
                unset($data[$this->getIdFieldName()]);
                $this->_getWriteAdapter()->update($this->getMainTable(), $data, $condition);
            } else {
                $select = $this->_getWriteAdapter()->select()
                    ->from($this->getMainTable(), array($this->getIdFieldName()))
                    ->where($condition);
                if ($this->_getWriteAdapter()->fetchOne($select) !== false) {
                    $data = $this->_prepareDataForSave($object);
                    unset($data[$this->getIdFieldName()]);
                    if (!empty($data)) {
                        $this->_getWriteAdapter()->update($this->getMainTable(), $data, $condition);
                    }
                } else {
                    $this->_getWriteAdapter()->insert($this->getMainTable(), $this->_prepareDataForSave($object));
                }
            }
        } else {
            $bind = $this->_prepareDataForSave($object);
            if ($this->_isPkAutoIncrement) {
                unset($bind[$this->getIdFieldName()]);
            }
            $this->_getWriteAdapter()->insert($this->getMainTable(), $bind);

            $object->setId($this->_getWriteAdapter()->lastInsertId($this->getMainTable()));

            if ($this->_useIsObjectNew) {
                $object->isObjectNew(false);
            }
        }

        $this->unserializeFields($object);
        $this->_afterSave($object);

        return $this;
    }