Back to Top

Magento 2 Development 07: Model, Resource Model, and Collection

Updated 5 March 2024

How to perform CRUD operations in Magento 2 – Now that we have created the tables. We need some way to manipulate (i.e. to perform CRUD operations) the table data of the database. To perform the CRUD (Create, Read, Update, Delete) operations we have to create these three classes (i.e. Model, Resource Model, and Collection) for each table. The name, Model comes from MVC (Model-View-Controller) architecture.

Model

The model represents a single entity. By that, I mean a single row of the table. The model provides a layer of abstraction over the resource model.

Let’s create a model for the “blogmanager_blog” table. For that inside our module folder create a folder named Model. Inside that folder create a Blog.php file,

Selection_092
Folder Structure

Code for Model/Blog.php file

<?php
namespace Webkul\BlogManager\Model;

class Blog extends \Magento\Framework\Model\AbstractModel implements \Magento\Framework\DataObject\IdentityInterface
{
    /**
     * No route page id.
     */
    const NOROUTE_ENTITY_ID = 'no-route';
    
    /**
     * Entity Id
     */
    const ENTITY_ID = 'entity_id';
    
    /**
     * BlogManager Blog cache tag.
     */
    const CACHE_TAG = 'webkul_blogmanager_blog';
    
    /**
     * @var string
     */
    protected $_cacheTag = 'webkul_blogmanager_blog';

    /**
     * @var string
     */
    protected $_eventPrefix = 'webkul_blogmanager_blog';
    
    /**
     * Dependency Initilization
     *
     * @return void
     */
    public function _construct()
    {
        $this->_init(\Webkul\BlogManager\Model\ResourceModel\Blog::class);
    }
    
    /**
     * Load object data.
     *
     * @param int $id
     * @param string|null $field
     * @return $this
     */
    public function load($id, $field = null)
    {
        if ($id === null) {
            return $this->noRoute();
        }
        return parent::load($id, $field);
    }
    
    /**
     * No Route
     *
     * @return $this
     */
    public function noRoute()
    {
        return $this->load(self::NOROUTE_ENTITY_ID, $this->getIdFieldName());
    }

    /**
     * Get Identities
     *
     * @return array
     */
    public function getIdentities()
    {
        return [self::CACHE_TAG.'_'.$this->getId()];
    }

    /**
     * Get Id
     *
     * @return int|null
     */
    public function getId()
    {
        return parent::getData(self::ENTITY_ID);
    }

    /**
     * Set Id
     *
     * @param int $id
     * @return \Webkul\BlogManager\Model\Blog
     */
    public function setId($id)
    {
        return $this->setData(self::ENTITY_ID, $id);
    }
}

The model class will extend \Magento\Framework\Model\AbstractModel and implements \Magento\Framework\DataObject\IdentityInterface. The IdentityInterface will force the Model class to define the getIdentities() method which will return a unique id for each model.

Searching for an experienced
Magento 2 Company ?
Find out More

Earlier I said “The model provides a layer of abstraction over the resource model.” by that I meant that we use the model class in our code to manipulate the tables but the actual query gets executed by the resource model class. So every model will require a resource model which will execute the actual SQL queries. When we create a new object the _construct method will get executed, which will call the init method where we have to pass the resource model as param.

Similarly, we need to create the model for the “blogmanager_comment” table as Model/Comment.php,

Selection_093
File Structure

Code for Model/Comment.php file

<?php
namespace Webkul\BlogManager\Model;

class Comment extends \Magento\Framework\Model\AbstractModel implements \Magento\Framework\DataObject\IdentityInterface
{
    /**
     * No route page id.
     */
    const NOROUTE_ENTITY_ID = 'no-route';
    
    /**
     * Entity Id
     */
    const ENTITY_ID = 'entity_id';
    
    /**
     * BlogManager Comment cache tag.
     */
    const CACHE_TAG = 'webkul_blogmanager_comment';
    
    /**
     * @var string
     */
    protected $_cacheTag = 'webkul_blogmanager_comment';

    /**
     * @var string
     */
    protected $_eventPrefix = 'webkul_blogmanager_comment';
    
    /**
     * Dependency Initilization
     *
     * @return void
     */
    public function _construct()
    {
        $this->_init(\Webkul\BlogManager\Model\ResourceModel\Comment::class);
    }
    
    /**
     * Load object data.
     *
     * @param int $id
     * @param string|null $field
     * @return $this
     */
    public function load($id, $field = null)
    {
        if ($id === null) {
            return $this->noRoute();
        }
        return parent::load($id, $field);
    }
    
    /**
     * No Route
     *
     * @return $this
     */
    public function noRoute()
    {
        return $this->load(self::NOROUTE_ENTITY_ID, $this->getIdFieldName());
    }

    /**
     * Get Identities
     *
     * @return array
     */
    public function getIdentities()
    {
        return [self::CACHE_TAG.'_'.$this->getId()];
    }

    /**
     * Get Id
     *
     * @return int|null
     */
    public function getId()
    {
        return parent::getData(self::ENTITY_ID);
    }

    /**
     * Set Id
     *
     * @param int $id
     * @return \Webkul\BlogManager\Model\Blog
     */
    public function setId($id)
    {
        return $this->setData(self::ENTITY_ID, $id);
    }
}

Resource Model

We have already discussed the importance of the resource model. So let’s just dive into code.

First, we will create the resource model for the “blogmanager_blog” table. For that, we have to create a ResourceModel folder under the Model folder, and inside that ResourceModel folder, we will create a Blog.php file.

Selection_094-1
Folder Structure

Code for Model/ResourceModel/Blog.php file

<?php
namespace Webkul\BlogManager\Model\ResourceModel;

class Blog extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
{
    /**
     * Dependency Initilization
     *
     * @return void
     */
    public function _construct()
    {
        $this->_init("blogmanager_blog", "entity_id");
    }
}

Here we have to mention our table name and the primary key of the table. All the resource model classes will extend \Magento\Framework\Model\ResourceModel\Db\AbstractDb class which have the common functions for actual database operations.

Similarly, we need to create the resource model for the “blogmanager_comment” table as Model/ResourceModel/Comment.php,

Selection_095
Folder Structure

Code for Model/ResourceModel/Comment.php file

<?php
namespace Webkul\BlogManager\Model\ResourceModel;

class Comment extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
{
    /**
     * Dependency Initilization
     *
     * @return void
     */
    public function _construct()
    {
        $this->_init("blogmanager_comment", "entity_id");
    }
}

Collection

We know that the model represents a single row of the table whereas the collection represents all the rows of the table. We can think of the collection as a collection of models or “Select * From Table table_name”.

So if we have to access all/multiple rows of the table, perform some filter with where/like, or perform some sorting with the order by then we should use collection.

Whereas if we have to insert a single row or fetch a single row or update some column in a row or delete a single row then we have to use a model.

Now let’s create a collection class for the “blogmanager_blog” table. For that, we have to create a folder with the same name as the resource model class name under the ResourceModel folder.

So here we will create a folder named Blog under Model/ResourceModel/ folder. And under that folder, we will create Collection.php class.

Selection_096
Folder Structure

Code for Model/ResourceModel/Blog/Collection.php file

<?php
namespace Webkul\BlogManager\Model\ResourceModel\Blog;

class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
{
    /**
     * @var string
     */
    protected $_idFieldName = 'entity_id';
    
    /**
     * Dependency Initilization
     *
     * @return void
     */
    public function _construct()
    {
        $this->_init(
            \Webkul\BlogManager\Model\Blog::class,
            \Webkul\BlogManager\Model\ResourceModel\Blog::class
        );
        $this->_map['fields']['entity_id'] = 'main_table.entity_id';
    }
}

Here we have to provide both the model and the resource model when we call the init method in the constructor.

Similarly, we can create the collection for the “blogmanager_comment” table as Model/ResourceModel/Comment/Collection.php,

Selection_097
Folder Structure

Code for Model/ResourceModel/Comment/Collection.php file

<?php
namespace Webkul\BlogManager\Model\ResourceModel\Comment;

class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
{
    /**
     * @var string
     */
    protected $_idFieldName = 'entity_id';
    
    /**
     * Dependency Initilization
     *
     * @return void
     */
    public function _construct()
    {
        $this->_init(
            \Webkul\BlogManager\Model\Comment::class,
            \Webkul\BlogManager\Model\ResourceModel\Comment::class
        );
        $this->_map['fields']['entity_id'] = 'main_table.entity_id';
    }
}

After creating all of the classes we need to run the di compile command. Which if you remembered was php bin/magento setup:di:compile

The di compile will generate some codes automatically which you can find in generated/code folder under the Magento root directory. We will learn in more detail about code generation in the later part of this blog series.

PS. Please check the namespace of the class if you get confused with the folder structure.

Here we learned why and how to create these classes. In the next blogs, we will see how to use them.

The folder structure till now should be like this,

Selection_098
Folder Structure

Next Blog -> Magento 2 Development 08: Layout and Templates

Previous Blog -> Magento 2 Development 06: Creating Tables

You can get more magento2 (Adobe Commerce) articles here.

. . .

Leave a Comment

Your email address will not be published. Required fields are marked*


Be the first to comment.

Back to Top

Message Sent!

If you have more details or questions, you can reply to the received confirmation email.

Back to Home