The latest versions of Magento Commerce and Magento Open Source v2.4 are now available. More info: https://bit.ly/3h5P28D

How to develop CRUD Module in Magento 2

Magento 2

With the CRUD operation, we can easily manipulate data into the database. It is not required to write many lines of code repeatedly for data manipulation. Magento 2 provides functions to easily manipulate data into the database. Below are listed main contents for CRUD module development –

  • Create Database Schema
  • Create Module
  • Read Data from table and display
  • Insert record
  • Update record
  • Delete record
Step 1 – Create Database Schema

To create the database table for CRUD operation initially insert the Setup file (InstallSchema.php):

app/code/Sparsh/CRUD/Setup/InstallSchema.php

The file will execute only one time when installing the module. Here ‘Sparsh’ is vendor name and ‘CRUD’ is a module name. Below is the snippet to create ‘post’ table for this –

namespace Sparsh\CRUD\Setup;
 
class InstallSchema implements \Magento\Framework\Setup\InstallSchemaInterface
{
        public function install(\Magento\Framework\Setup\SchemaSetupInterface $setup, \Magento\Framework\Setup\ModuleContextInterface $context)
        {
                $installer = $setup;
                $installer->startSetup();
                if (!$installer->tableExists('post')) {
                        $table = $installer->getConnection()->newTable(
                                $installer->getTable('post')
                        )
                                ->addColumn(
                                        'post_id',
                                        \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
                                        null,
                                        [
                                                'identity' => true,
                                                'nullable' => false,
                                                'primary'  => true,
                                                'unsigned' => true,
                                        ],
                                        'Post ID'
                                )
                                ->addColumn(
                                        'name',
                                        \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                                        255,
                                        ['nullable => false'],
                                        'Post Name'
                                )
                                ->addColumn(
                                        'url_key',
                                        \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                                        255,
                                        [],
                                        'Post URL Key'
                                )
                                ->addColumn(
                                        'post_content',
                                        \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                                        '64k',
                                        [],
                                        'Post Post Content'
                                )
                                ->addColumn(
                                        'tags',
                                        \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                                        255,
                                        [],
                                        'Post Tags'
                                )
                                ->addColumn(
                                        'status',
                                        \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
                                        1,
                                        [],
                                        'Post Status'
                                )
                                ->addColumn(
                                        'featured_image',
                                        \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                                        255,
                                        [],
                                        'Post Featured Image'
                                )
                                ->addColumn(
                                                'created_at',
                                                \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP,
                                                null,
                                                ['nullable' => false, 'default' => \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT],
                                                'Created At'
                                )->addColumn(
                                        'updated_at',
                                        \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP,
                                        null,
                                        ['nullable' => false, 'default' => \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT_UPDATE],
                                        'Updated At')
                                ->setComment('Post Table');
                        $installer->getConnection()->createTable($table);
 
                        $installer->getConnection()->addIndex(
                                $installer->getTable('post'),
                                $setup->getIdxName(
                                        $installer->getTable('post'),
                                        ['name','url_key','post_content','tags','featured_image'],
                                        \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_FULLTEXT
                                ),
                                ['name','url_key','post_content','tags','featured_image'],
                                \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_FULLTEXT
                        );
                }
                $installer->endSetup();
        }
}

Magento web development services automatically run the above-mentioned file for the first time while installing the module. If you have already installed the module prior, it is required to upgrade module and add the table create code to the ‘UpgradeSchema.php’ in that folder and change attribute setup version greater than current setup version in module.xml. Module.xml is located at below path,

app/code/Sparsh/CRUD/etc/module.xml

Include below snippet to create ‘post’ table in the file-

namespace Sparsh\CRUD\Setup;
 
use Magento\Framework\Setup\UpgradeSchemaInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Framework\Setup\ModuleContextInterface;
 
class UpgradeSchema implements UpgradeSchemaInterface
{
        public function upgrade( SchemaSetupInterface $setup, ModuleContextInterface $context ) {
                $installer = $setup;
 
                $installer->startSetup();
 
                if(version_compare($context->getVersion(), '1.1.0', '<')) { if (!$installer->tableExists('post')) {
                                $table = $installer->getConnection()->newTable(
                                        $installer->getTable('post')
                                )
                                        ->addColumn(
                                                'post_id',
                                                \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
                                                null,
                                                [
                                                        'identity' => true,
                                                        'nullable' => false,
                                                        'primary'  => true,
                                                        'unsigned' => true,
                                                ],
                                                'Post ID'
                                        )
                                        ->addColumn(
                                                'name',
                                                \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                                                255,
                                                ['nullable => false'],
                                                'Post Name'
                                        )
                                        ->addColumn(
                                                'url_key',
                                                \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                                                255,
                                                [],
                                                'Post URL Key'
                                        )
                                        ->addColumn(
                                                'post_content',
                                                \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                                                '64k',
                                                [],
                                                'Post Post Content'
                                        )
                                        ->addColumn(
                                                'tags',
                                                \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                                                255,
                                                [],
                                                'Post Tags'
                                        )
                                        ->addColumn(
                                                'status',
                                                \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
                                                1,
                                                [],
                                                'Post Status'
                                        )
                                        ->addColumn(
                                                'featured_image',
                                                \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                                                255,
                                                [],
                                                'Post Featured Image'
                                        )
                                        ->addColumn(
                                                'created_at',
                                                \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP,
                                                null,
                                                ['nullable' => false, 'default' => \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT],
                                                'Created At'
                                        )->addColumn(
                                                'updated_at',
                                                \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP,
                                                null,
                                                ['nullable' => false, 'default' => \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT_UPDATE],
                                                'Updated At')
                                        ->setComment('Post Table');
                                $installer->getConnection()->createTable($table);
 
                                $installer->getConnection()->addIndex(
                                        $installer->getTable('post'),
                                        $setup->getIdxName(
                                                $installer->getTable('post'),
                                                ['name','url_key','post_content','tags','featured_image'],
                                                \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_FULLTEXT
                                        ),
                                        ['name','url_key','post_content','tags','featured_image'],
                                        \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_FULLTEXT
                                );
                        }
                }
 
                $installer->endSetup();
        }
}

Now, run the below command line –

php bin/magento setup:upgrade

When you run upgrade completed, continue to run and deploy like below –

php bin/magento setup:static-content:deploy

Now, while checking database, you can see a table with name ‘post’ and along with columns created. This ‘InstallSchema.php’ is used to create database structure. If you want to install data to the table which you have created, then use ‘InstallData.php’ file –

app/code/Sparsh/CRUD/Setup/InstallData.php

If you want to change the database when upgrade module, please try to use ‘UpgradeSchema.php’ and ‘UpgradeData.php’. Top Magento developers recommend to perform each of the steps to create the solution efficiently.

Step 2 – Create Module

Name of the module is defined as /. First part is name of the vendor and last part is name of the module. For example: Sparsh/CRUD. Focus on following guide to create the folders:

app/code/Sparsh/CRUD

Create etc/module.xml file. It is necessery to create etc folder and add ‘module.xml’ file.

app/code/Sparsh/CRUD/etc/module.xml

Let add below snippet for this file:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Sparsh_CRUD" setup_version="1.1.0">
    </module>
</config>

Here you can see that name attribute is our module name and setup_version which will be use full in upgrade database schema. Create etc/registration.php file. In this step, we will add ‘registration.php’ to register CRUD module.

app/code/Sparsh/CRUD/registration.php
Let put below content for this file :
\Magento\Framework\Component\ComponentRegistrar::register(
        \Magento\Framework\Component\ComponentRegistrar::MODULE,
        'Sparsh_CRUD',
        __DIR__
);

Enable the CRUD module. After this, run the below command in command line

php bin/magento module:status

After execute above command in command line, it will list all Magento modules and here you should see currently created module (Sparsh_CRUD) is disable. To enable created Sparsh_CRUD module please run the below command in command line,

php bin/magento module:enable Sparsh_CRUD

After the above command execution complete, you can see ‘Sparsh_CRUD’ => 1 in app/etc/config.php file.

Upgrade Setup. After above process, when you open your website in browser you might get an error, upgrade your database: Run php bin/magento setup:upgrade from the Magento root directory. Run the below command in command line in that case:

php bin/magento setup:upgrade

After complete, when you open your website in browser you will see the layout of the website is broken.

website-Layout-Broken

Please run the deploy command in command line to fix it,

php bin/magento setup:static-content:deploy

Create Route. Route’s in Magento is divided into 3 parts: Route Frontname, Controller and Action as the following example:

http:///frontname/controller/action

To add the route, it is necessary to create routes.xml file

app/code/Sparsh/CRUD/etc/frontend/routes.xml

Snippet:

<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="standard">
        <route frontName="crud" id="crud">
            <module name="Sparsh_CRUD"/>
        </route>
    </router>
</config>

After defining the first part of the route, the URL will be displayed as:

http:///crud/*

Create Controller and Action. After creating route continue to create controller and action. The folder and file you need to create is

app/code/Sparsh/CRUD/Controller/Index/Index.php

Below is the snippet that is to be included in this file :

namespace Sparsh\CRUD\Controller\Index;
 
class Index extends \Magento\Framework\App\Action\Action
{
     protected $_pageFactory;
 
     public function __construct(
          \Magento\Framework\App\Action\Context $context,
          \Magento\Framework\View\Result\PageFactory $pageFactory
          )
     {
          $this->_pageFactory = $pageFactory;
          return parent::__construct($context);
     }
 
     public function execute()
     {
          echo “Module Created Successfully”;
     }
}

Cache Clean. After completed, please run php bin/magento cahce:clean to check result. Your URL should be as:

	http:///crud/index/index
Step 3 – Read Data from Table and Display

Create Model. Magento 2 CRUD, models have many different functions such as manage data, install module, upgrade module. We have to create Model, Resource Model, Resource Model Collection to manage manipulate data in table. Now we will create the model file:

app/code/Sparsh/CRUD/Model/Post.php

Below is the code snippet to be included for this file:

namespace Sparsh\CRUD\Model;
 
class Post extends \Magento\Framework\Model\AbstractModel implements \Magento\Framework\DataObject\IdentityInterface
{
        protected function _construct()
        {
                $this->_init('Sparsh\CRUD\Model\ResourceModel\Post');
        }
 
        public function getIdentities()
        {
                return [self::CACHE_TAG . '_' . $this->getId()];
        }
 
        public function getDefaultValues()
        {
                $values = [];
 
                return $values;
        }
}

Create Resource Model Collection. The collection model is considered a resource model which allow us to filter and fetch a collection table data. The collection model will be placed at below path –

	app/code/Sparsh/CRUD/Model/ResourceModel/Post/Collection.php

Include below snippet in this file:

namespace Sparsh\CRUD\Model\ResourceModel\Post;
 
class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
{
        /**
         * Define resource model
         *
         * @return void
         */
        protected function _construct()
        {
                $this->_init('Sparsh\CRUD\Model\Post', 'Sparsh\CRUD\Model\ResourceModel\Post');
        }
}

Create page factory object and return from controller execute method –

app/code/Sparsh/CRUD/Controller/Index/Index.php

Include below snippet for this file:

    public function execute()
     {
          return $this->_pageFactory->create();
     }

Create layout file

app/code/Sparsh/CRUD/view/frontend/layout/crud_index_index.xml

Include below snippet in this file:

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <referenceContainer name="content">
        <block class="Sparsh\CRUD\Block\Index" name="crud_index_index" template="Sparsh_CRUD::index.phtml" />
    </referenceContainer>
</page>

Create block file and fetch record from post table

app/code/Sparsh/CRUD/Block/Index.php

Include below snippet in this file:

namespace Sparsh\CRUD\Block;
 
use Magento\Framework\App\Filesystem\DirectoryList;
 
class Index extends \Magento\Framework\View\Element\Template
{
     protected $_filesystem;
 
     public function __construct(
          \Magento\Framework\View\Element\Template\Context $context,
          \Sparsh\CRUD\Model\PostFactory $postFactory
          )
     {
          parent::__construct($context);
          $this->_postFactory = $postFactory;
     }
 
     public function getResult()
     {
          $post = $this->_postFactory->create();
          $collection = $post->getCollection();
          return $collection;
     }
}

Create Template File and display fetch data

app/code/Sparsh/CRUD/view/frontend/templates/index.phtml

Include below snippet in this file:

<table>
     <tr>
          <th>Id</th>
          <th>Name</th>
          <th>Created At</th>
          <th>Updated At</th>
          <th colspan="2">Action</th>
     </tr>
 
     <?php
          $collection = $block->getResult();
          foreach($collection as $item){
     ?>
     <tr>
          <td><?php echo $item->getData('post_id'); ?></td>
          <td><?php echo $item->getDate('name); ?></td>
          <td><?php echo $item->getData('created_at); ?></td>
          <td><?php echo $item->getData('updated_at); ?></td>
          <td><a href="<?php echo $block->getUrl('crud/index/edit').'id/'.$item->getData('post_id'); ?>" class="action primary">Edit</a></td>
          <td><a href="<?php echo $block->getUrl('crud/index/delete').'?id='.$item->getData('post_id'); ?>" class="action primary">Delete</a></td>
     </tr>
     <?php } ?>
</table>

Cache clean. After completed, please run php bin/magento cahce:clean to check result. Your URL should be as:

http:///crud/index/index
Step 4 – Insert Record

Define insert route and create controller and action. Add insert route in index.phtml file

app/code/Sparsh/CRUD/view/frontend/templates/index.phtml

Include below snippet in this file:

<a class="action primary" href=" echo $block->getUrl('crud/index/insert'); ">Add Record</a>

As discussed previously that our route is divided into three parts –
Crud is , Index is and is Action Name.

App/code/Sparsh/CRUD/Controller/Index/Insert.php

Include below snippet in this file:

namespace Sparsh\CRUD\Controller\Index;
 
class Insert extends \Magento\Framework\App\Action\Action
{
     protected $_pageFactory;
 
     public function __construct(
          \Magento\Framework\App\Action\Context $context,
          \Magento\Framework\View\Result\PageFactory $pageFactory
          )
     {
          $this->_pageFactory = $pageFactory;
          return parent::__construct($context);
     }
 
     public function execute()
     {
          return $this->_pageFactory->create();
     }
}

Create Layout File

app/code/Sparsh/CRUD/view/frontend/layout/crud_index_insert.xml

Include below snippet in this file:

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
 
    <referenceContainer name="content">
        <block class="Sparsh\CRUD\Block\Insert" name="crud_index_insert" template="Sparsh_CRUD::insert.phtml" cacheable="false" />
    </referenceContainer>
</page>

Create block file

app/code/Sparsh/CRUD/Block/Insert.php

Include below snippet in this file:

namespace Sparsh\CRUD\Block;
 
class Insert extends \Magento\Framework\View\Element\Template
{
     protected $_pageFactory;
     protected $_postLoader;
 
     public function __construct(
          \Magento\Framework\View\Element\Template\Context $context,
          \Magento\Framework\View\Result\PageFactory $pageFactory
          )
     {
          $this->_pageFactory = $pageFactory;
          return parent::__construct($context);
     }
 
     public function execute()
     {
          return $this->_pageFactory->create();
     }
}

Create template file

app/code/Sparsh/CRUD/view/frontend/templates/insert.phtml

Include below snippet in this file:

 $record = $block->getEditRecord();

Create Save action to save the record

app\code\Sparsh\CRUD\Controller\Index\Save.php
 
 
Include below snippet in this file:
namespace Sparsh\CRUD\Controller\Index;
 
use Magento\Framework\App\Filesystem\DirectoryList;
 
class Save extends \Magento\Framework\App\Action\Action
{
     protected $_pageFactory;
     protected $_postFactory;
     protected $_filesystem;
 
     public function __construct(
          \Magento\Framework\App\Action\Context $context,
          \Magento\Framework\View\Result\PageFactory $pageFactory,
          \Sparsh\CRUD\Model\PostFactory $postFactory,
          \Magento\Framework\Filesystem $filesystem
          )
     {
          $this->_pageFactory = $pageFactory;
          $this->_postFactory = $postFactory;
          $this->_filesystem = $filesystem;
          return parent::__construct($context);
     }
 
     public function execute()
     {
          if ($this->getRequest()->isPost()) {
               $input = $this->getRequest()->getPostValue();
               $post = $this->_postFactory->create();
 
          if($input['editRecordId']){
                    $post->load($input['editRecordId']);
                    $post->addData($input);
                    $post->setId($input['editRecordId']);
                    $post->save();
          }else{
               $post->setData($input)->save();
          }
 
              return $this->_redirect('crud/index/index');
          }
     }
}

Cache clean. After completed, please run php bin/magento cahce:clean to check result. Your URL should be as:

http:///crud/index/insert
Step 5 – Update Record

Define edit route and create controller and action. Add edit route in index.phtml file

app/code/Sparsh/CRUD/view/frontend/templates/index.phtml

Include below snippet in this file:

<a class="action primary" href=" echo $block->getUrl('crud/index/edit').'id/'.$item->getData('id'); ">Edit</a>

As discussed previously, our route is divided into three part – Crud is , Index is and is Action Name.

App/code/Sparsh/CRUD/Controller/Index/Edit.php

Include below snippet in this file:

namespace Sparsh\CRUD\Controller\Index;
 
class Edit extends \Magento\Framework\App\Action\Action
{
     protected $_pageFactory;
     protected $_request;
     protected $_coreRegistry;
 
     public function __construct(
          \Magento\Framework\App\Action\Context $context,
          \Magento\Framework\View\Result\PageFactory $pageFactory,
          \Magento\Framework\App\Request\Http $request,
          \Magento\Framework\Registry $coreRegistry
          )
     {
          $this->_pageFactory = $pageFactory;
          $this->_request = $request;
          $this->_coreRegistry = $coreRegistry;
          return parent::__construct($context);
     }
 
     public function execute()
     {
        $id = $this->_request->getParam('id');
        $this->_coreRegistry->register('editRecordId', $id);
          return $this->_pageFactory->create();
     }
}

Create Layout File:

app/code/Sparsh/CRUD/view/frontend/layout/crud_index_edit.xml

Include below snippet in this file:

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <referenceContainer name="content">
        <block class="Sparsh\CRUD\Block\Edit" name="crud_index_edit" template="Sparsh_CRUD::insert.phtml" cacheable="false"/>
    </referenceContainer>
</page>

Create block file

app/code/Sparsh/CRUD/Block/Edit.php

Include below snippet in this file:

namespace Sparsh\CRUD\Block;
 
class Edit extends \Magento\Framework\View\Element\Template
{
     protected $_pageFactory;
     protected $_coreRegistry;
     protected $_postLoader;
 
     public function __construct(
          \Magento\Framework\View\Element\Template\Context $context,
          \Magento\Framework\View\Result\PageFactory $pageFactory,
          \Magento\Framework\Registry $coreRegistry,
          \Sparsh\HelloWorld\Model\PostFactory $postLoader,
          array $data = []
          )
     {
          $this->_pageFactory = $pageFactory;
          $this->_coreRegistry = $coreRegistry;
          $this->_postLoader = $postLoader;
          return parent::__construct($context,$data);
     }
 
     public function execute()
     {
          return $this->_pageFactory->create();
     }
 
     public function getEditRecord()
     {
          $id = $this->_coreRegistry->registry('editRecordId');
               $post = $this->_postLoader->create();
          $result = $post->load($id);
          $result = $result->getData();
               return $result;
     }
}

Cache clean. After completed, please run php bin/magento cahce:clean to check result. Your URL should be as:

http:///crud/index/index
Step 6 – Delete Record

Define delete route and create controller and action. Add delete route in index.phtml file.

app/code/Sparsh/CRUD/view/frontend/templates/index.phtml

Include below snippet in this file –

<a class="action primary" href=" echo $block->getUrl('crud/index/delete').'?id='.$item->getData('id'); ">Delete</a>

As discussed previously that our route is divided into three part – Crud is , Index is and is Action Name.

App/code/Sparsh/CRUD/Controller/Index/Delete.php

Include below snippet in this file –

namespace Sparsh\CRUD\Controller\Index;
 
class Delete extends \Magento\Framework\App\Action\Action
{
     protected $_pageFactory;
     protected $_request;
     protected $_postFactory;
 
     public function __construct(
          \Magento\Framework\App\Action\Context $context,
          \Magento\Framework\View\Result\PageFactory $pageFactory,
          \Magento\Framework\App\Request\Http $request,
          \Sparsh\HelloWorld\Model\PostFactory $postFactory
          )
     {
          $this->_pageFactory = $pageFactory;
          $this->_request = $request;
          $this->_postFactory = $postFactory;
          return parent::__construct($context);
     }
 
     public function execute()
     {
               $id = $this->_request->getParam('id');
          $post = $this->_postFactory->create();
          $result = $post->setId($id);
          $result = $result->delete();
          return $this->_redirect('crud/index/index');
     }
}

Cache clean. After completed, please run php bin/magento cahce:clean to check result. Your URL should be as:

	http:///crud/index/index

Tell us about your project

Hire dedicated Magento developer from the vast and talented pool of resources.