Quantcast
Channel: Webkul Blog
Viewing all articles
Browse latest Browse all 5490

Working With Database Transactions In Magento2

$
0
0

Introduction

In a structure like magento2, it is very difficult to guarantee the consistency of data, the system of EAV(Entity Attribute Value) makes magento2 highly scalable and modular but every thing comes with a cost, managing the data in these structures can be very difficult. To ensure the consistency of data, magento2 uses database transactions.

Whenever we save a model in Magento, it gets executed as a transaction, when you will dig deeper and check the Magento\Framework\Model\AbstractModel class you will found the save function:

    public function save()
    {
        $this->_getResource()->save($this);
        return $this;
    }

you can see that the save method is calling another save method from resource class, even the delete method calls the delete method of the resource model class, so resource model is responsible for saving, updating, deleting rows from the database.

Let’s check the resource model save method when you will check the resource model parent class, you will find this class:

Magento\Framework\Model\ResourceModel\Db\AbstractDb and the save method is defined in the class, although you can override the save method in the resource model concrete class, you still need to call the parent class “save” method:

public function save(\Magento\Framework\Model\AbstractModel $object)
    {
        if ($object->isDeleted()) {
            return $this->delete($object);
        }

        $this->beginTransaction();

        try {
            if (!$this->isModified($object)) {
                $this->processNotModifiedSave($object);
                $this->commit();
                $object->setHasDataChanges(false);
                return $this;
            }
            $object->validateBeforeSave();
            $object->beforeSave();
            if ($object->isSaveAllowed()) {
                $this->_serializeFields($object);
                $this->_beforeSave($object);
                $this->_checkUnique($object);
                $this->objectRelationProcessor->validateDataIntegrity($this->getMainTable(), $object->getData());
                if ($this->isObjectNotNew($object)) {
                    $this->updateObject($object);
                } else {
                    $this->saveNewObject($object);
                }
                $this->unserializeFields($object);
                $this->processAfterSaves($object);
            }
            $this->addCommitCallback([$object, 'afterCommitCallback'])->commit();
            $object->setHasDataChanges(false);
        } catch (\Exception $e) {
            $this->rollBack();
            $object->setHasDataChanges(true);
            throw $e;
        }
        return $this;
    }

The above code is also very abstract, but still pretty much understandable, thanks to great naming sense by the Magento developers. The methods those are related to transactions are:

  • beginTransaction: this method starts the transaction.
  • commit: this method commits the transaction, we should only call the commit until and unless it is assured that everything is correct because there is no rolling back after commit.
  • rollBack: this is used to roll back all the changes in the tables if any exception arises, as you can see it is called in the catch block of exception handling.

the above save method could be similar to the raw SQL code:

START TRANSACTION

//multiple queries can be defined here to save or update the database tables

COMMIT or ROLLBACK

That’s how Magento uses transactions while you save or update any models. you can even create an observer to make some checks before commit and if your check fails just throw an error and every thing will be rolled back.

If you check the function processAfterSaves:

    protected function processAfterSaves(\Magento\Framework\Model\AbstractModel $object)
    {
        $this->_afterSave($object);
        $object->afterSave();
    }

in the above method, you can see the object’s(this object can be any model class) afterSave method is called, the afterSave method of model resides in class Magento\Framework\Model\AbstractModel\

    public function afterSave()
    {
        $this->cleanModelCache();
        $this->_eventManager->dispatch('model_save_after', ['object' => $this]);
        $this->_eventManager->dispatch('clean_cache_by_tags', ['object' => $this]);
        $this->_eventManager->dispatch($this->_eventPrefix . '_save_after', $this->_getEventData());
        $this->updateStoredData();
        return $this;
    }

in the above method you can see there is an event dispatched, with a dynamic string included in the name:

$this->_eventPrefix this returns the model’s events prefix name that you define in your model class, in the case of order model it is sales_order, so the after saving event for the order model will be:

sales_order_after_save similarly you can predict any model class after save observer event name. Using this event you can put your code before commit and can easily roll back any incorrect updates.

Hope this will help you in solving your issues. If you have any issues or doubts in the above explanation you can ask in the comments, I will try my best to answer you.

Thanks 🙂


Viewing all articles
Browse latest Browse all 5490

Trending Articles