Create a Magento 2 Model and Database Layer
In Magento 2, models, resource models, and collections work together to handle data storage and retrieval. Models encapsulate business logic, resource models contain database-specific logic, and collections help you work with multiple rows (entities) at once.
1. Create the Model Class
The model represents a single entity (row) from your custom table. It should not contain raw SQL. Instead, it delegates all database operations to the resource model.
File: app/code/Hikmadh/Mymodule/Model/Contact.php
<?php namespace Hikmadh\Mymodule\Model; use Magento\Framework\Model\AbstractModel; /**
* Contact Model
*/
class Contact extends AbstractModel
{
/**
* Initialize resource model
*/
protected function _construct()
{
$this->_init(\Hikmadh\Mymodule\Model\ResourceModel\Contact::class);
}
}2. Create the ResourceModel Class
The resource model contains table and primary key information, and it’s responsible
for all low-level DB operations. The model calls into this class when you use save(), load(), or collections.
File: app/code/Hikmadh/Mymodule/Model/ResourceModel/Contact.php
<?php namespace Hikmadh\Mymodule\Model\ResourceModel; use Magento\Framework\Model\ResourceModel\Db\AbstractDb; /**
* Contact Resource Model
*/
class Contact extends AbstractDb
{
/**
* Initialize resource
*/
protected function _construct()
{
// 'hikmadh_mymodule' = table name
// 'hikmadh_mymodule_id' = primary key column
$this->_init('hikmadh_mymodule', 'hikmadh_mymodule_id');
}
}3. Create the Collection Class
A collection is used to load multiple entities, apply filters, and iterate over the result set. It is tied to your model and resource model.
File: app/code/Hikmadh/Mymodule/Model/ResourceModel/Contact/Collection.php
<?php namespace Hikmadh\Mymodule\Model\ResourceModel\Contact; use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection; /**
* Contact Resource Model Collection
*/
class Collection extends AbstractCollection
{
/**
* Initialize resource collection
*/
protected function _construct()
{
$this->_init(
\Hikmadh\Mymodule\Model\Contact::class,
\Hikmadh\Mymodule\Model\ResourceModel\Contact::class
);
}
}4. (Optional but Recommended) Define the Database Table (db_schema.xml)
In modern Magento 2 (declarative schema), you define your table in db_schema.xml. This file creates the hikmadh_mymodule table with an auto-increment primary key and a name column, which our model uses via the setName() method.
File: app/code/Hikmadh/Mymodule/etc/db_schema.xml
<?xml version="1.0"?>
<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd"> <table name="hikmadh_mymodule" resource="default" engine="innodb" comment="Hikmadh Contacts">
<column xsi:type="int" name="hikmadh_mymodule_id" padding="10" unsigned="true"
nullable="false" identity="true" comment="Entity ID" /> <column xsi:type="varchar" name="name" nullable="false" length="255"
comment="Contact Name" /> <constraint xsi:type="primary" referenceId="PRIMARY">
<column name="hikmadh_mymodule_id" />
</constraint>
</table> </schema>Run the usual setup upgrade command after adding this file:
php bin/magento setup:upgrade5. Create Contacts from the Controller (Using Dependency Injection)
To test the model and database integration, you can create a controller that
instantiates the Contact model and saves records into the table.
Here’s a best-practice example using a factory instead of the object manager.
File: app/code/Hikmadh/Mymodule/Controller/Test/Index.php
<?php namespace Hikmadh\Mymodule\Controller\Test; use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Hikmadh\Mymodule\Model\ContactFactory; class Index extends Action
{
/**
* @var ContactFactory
*/
protected $contactFactory; public function __construct(
Context $context,
ContactFactory $contactFactory
) {
$this->contactFactory = $contactFactory;
parent::__construct($context);
} public function execute()
{
$names = [
'Hikmadh Noor',
'Hikmadh Harun',
'Hikmadh Mohamed'
]; foreach ($names as $name) {
/** @var \Hikmadh\Mymodule\Model\Contact $contact */
$contact = $this->contactFactory->create();
$contact->setName($name);
$contact->save();
} $this->getResponse()->setBody('test');
}
}After deploying and clearing caches, visit:
http://www.example.com/index.php/mymodule/test/index You should see the response test, and all three contacts will be
inserted into your hikmadh_mymodule table. Open your database (MySQL)
and verify that the rows were created successfully.
6. Summary
- Model – wraps business logic for a single entity.
- ResourceModel – knows the table and primary key, handles DB I/O.
- Collection – loads multiple entities with filters.
- db_schema.xml – declarative schema to create/update DB tables.
- Controller – uses the model (via factory) to create and save data.
Together, these pieces form the standard Magento 2 persistence layer for your custom module, giving you a clean and extensible way to work with your own database tables.