Database in Magento 2: Models, Resource Models, and Collections.

Database in Magento 2: Models, Resource Models, and Collections.

The Magento ORM is used by the Repository implementations that are part of the Magento 2 service contracts. This is an important variation from Magento 1, as a module should no longer rely on other modules using a specific ORM, and instead of it use only the entity repositories. The service contracts will be covered in more details in the second part of the article.

The Magento ORM is built around models, resource models, and resource collections. The Magento ORM elements are following:

  • Models are data and behavior, representing entities.
  • Resource Models are data mappers for the storage structure.
  • Collections are encapsulating sets of models and related functionality, such as filtering, sorting, and paging.
  • Resources include database connections via adapters.

The ORM gives you a possibility to create, load, update, and delete data to a database. A collection in Magento is a class that implements both the IteratorAggregate and the Countable PHP5 SPL interfaces. Collections are widely used in Magento to store a set of objects of a specific type.

Database in Magento2. Part 1. Models, resource models, and collections.1

The Magento ORM concept requires that only models can contain and manipulate data. Magento has a very flexible and highly abstract concept of what a model is. Anything represented by a database table is most likely going to be a model.

When creating a new model that interfaces with the database, the model needs to know which resource model should be used. That’s why the class name of the resource model is specified by using the _init() method in the protected function _construct(). This is required to support the inherited AbstractModel methods getResource() and getCollection().

To create the model, you just create a class and extend it from \Magento\Framework\Model\AbstractModel. With Magento 2, you no longer have to declare the model, resource model, adapters, and more in the configuration. So the process is much simpler than in Magento 1. You just create the model class and extend it from the Magento framework AbstractModel.

Note that you call _init from a single-underscore construct method, not the real double underscore PHP constructor. This single-underscore _construct() method is also the legacy from Magento 1 and is called by the real __construct() method inherited from AbstractModel. A resource model extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb.

Again, note the single-underscore construct method. Do not confuse it with the real PHP constructor. You need to define the table name and the primary key field name for the resource model because it’s necessary to know where to save the model state. They are specified by calling the _init() method in the protected _construct() method.

The collection extends Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection.

When creating a resource collection, you need to specify which model it corresponds to, so that it can instantiate the appropriate classes after loading a list of records. It’s also necessary to know the matching resource model to be able to access the database. That’s why the class names of the model and the resource model are specified by using the _init() method in the protected _construct() method.

In Magento2 database connection settings are contained in the <Magento base dir>/app/etc/env.php file:

Magento2 model contains the deprecated CRUD (“CRUD” stands for “Create, Read, Update, Delete.”) methods load(), save(), and delete(), that delegate to the resource model. Developers striving to write upgrade safe code should not use the CRUD methods on the model, as they will be removed at some point in the future. Instead, the models should be passed directly to the CRUD methods on the resource model.

The model has no direct access to the database, only the resource models. So, if you need some special data from the database, you have to create the appropriate method on the resource model.

Actually the method does both: If the $isDeleted parameter is specified, it sets the _isDeleted flag value; otherwise, it returns the current flag value. The method validateBeforeSave() uses a validator, which contains all the rules to validate the current model. It is called by the resource model save() method.

In the resource model save() method, the _dataSaveAllowed flag can stop saving after the beforeSave() method was called. This can be helpful in case some data validation failed. The resource models method save() checks saved object and runs updateObject() and saveNewObject(), which of them use \Magento\Framework\DB\Adapter\AdapterInterface object for working with databases. Mechanism of the method load() is similar:

The deprecated model load() method internally calls the method _beforeLoad(), which triggers two events model_load_before and [event-prefix]_load_before. These events are well known for Magento 1 developers.

Since the model load method will be removed at some point in the future, it is better to use plugins into the resource model load method instead of relying on these events.

The _afterLoad method is used for processing an object directly after loading the data. Every time a Magento model is loaded, you can intercept it by observing the events model_load_before and model_load_after, which carries a simple data transfer object. The model instance itself is the key “object”.

As you can see on the slide, there is a more specific event also, which uses an entity-specific “prefix”. In Magento, most of the core models redefine the internal variable “_eventPrefix”, so one can observe CRUD operations for specific models. To determine the prefix used for a model, you need to check the model source code.

The resource models access the database through \Magento\Framework\Db\Adapter\Pdo and Zend\Db.

The API you program against for collections is implemented by \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection.

Database in Magento2. Part 1. Models, resource models, and collections.2

The programmatic API for collections is implemented by \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection.

Collections provide several useful functions for defining and working with a result set. As you can see, the set of methods exposed by collections has not changed much from Magento 1.

Database in Magento2. Part 1. Models, resource models, and collections.3

This diagram shows how a collection is loaded. It has not changed much since Magento 1.

A resource collection is necessary to create a set of model instances and operate on them. Resource collections lazy load the record set they represent. The first time the item list is accessed, a collection will load automatically. After that, a collection will not load again, even if the load() method is explicitly called.

Collections are very close to the database layer. Their task is to retrieve a set of rows from the database, then iterate over them, and for each row, instantiate the matching model class.

It solves these main issues:

  • Provides a container for storing collections of objects.
  • Prevents unnecessary data loading.
  • Stores all objects during a session.
  • Provides an interface for filtering and sorting entities of a specific kind.

Please check the second part of the article: Database in Magento 2: Service Contracts

Post a new comment

BelVG Newsletter
Subscribe to our mailing list and get interesting stuff and updates to your email inbox.
Email *