Skip to content
intermediate Phase 35 · Models

Magento Models

ExtensibleObject, data interfaces, model loading, save/delete, and model architecture.

45m
0 problems
Topic Progress 0%

Model Architecture

Magento models follow a three-layer architecture: Model, Resource Model, Collection.

Architecture:

Model (business logic)
├── Resource Model (database operations)
└── Collection (multiple models query)

Basic model:

<?php
namespace Vendor\Blog\Model;

use Magento\Framework\Model\AbstractModel;

class Post extends AbstractModel
{
    protected function _construct()
    {
        $this->_init(\Vendor\Blog\Model\ResourceModel\Post::class);
    }
    
    // Getters and setters
    public function getTitle(): string
    {
        return $this->getData('title');
    }
    
    public function setTitle(string $title): self
    {
        return $this->setData('title', $title);
    }
}

Model with data interface:

<?php
namespace Vendor\Blog\Model;

use Magento\Framework\Model\AbstractModel;
use Vendor\Blog\Api\Data\PostInterface;

class Post extends AbstractModel implements PostInterface
{
    protected function _construct()
    {
        $this->_init(\Vendor\Blog\Model\ResourceModel\Post::class);
    }
    
    public function getTitle(): string
    {
        return $this->getData(self::TITLE);
    }
    
    public function setTitle(string $title): PostInterface
    {
        return $this->setData(self::TITLE, $title);
    }
}

Data Interfaces

Data interfaces define the API contract for models.

Data interface:

<?php
namespace Vendor\Blog\Api\Data;

interface PostInterface
{
    const TITLE = 'title';
    const CONTENT = 'content';
    const STATUS = 'status';
    const CREATED_AT = 'created_at';
    
    public function getId(): ?int;
    public function getTitle(): string;
    public function setTitle(string $title): self;
    public function getContent(): string;
    public function setContent(string $content): self;
    public function getStatus(): int;
    public function setStatus(int $status): self;
}

Extension attributes:

<?php
namespace Vendor\Blog\Api\Data;

interface PostExtensionAttributesInterface
{
    public function getAuthorName(): ?string;
    public function setAuthorName(string $authorName): self;
    public function getTags(): ?array;
    public function setTags(array $tags): self;
}

Using data interfaces:

// Repository returns interface
$post = $this->postRepository->getById(1);

// Type-hint against interface
public function save(PostInterface $post): PostInterface
{
    // Work with interface, not concrete class
    $title = $post->getTitle();
    $post->setTitle('New Title');
    
    return $this->postRepository->save($post);
}

Model Loading and Save/Delete

CRUD operations through models.

Loading a model:

// Load by ID
$post = $this->postFactory->create()->load($id);

// Load by attribute
$post = $this->postFactory->create();
$post->load('my-url-key', 'url_key');

// Load by ID via resource model
$resource = $this->postFactory->create()->getResource();
$resource->load($post, $id);

Saving a model:

// Create new
$post = $this->postFactory->create();
$post->setTitle('My Post');
$post->setContent('Content');
$post->save();

// Update existing
$post = $this->postFactory->create()->load(1);
$post->setTitle('Updated Title');
$post->save();

// Save with data
$post = $this->postFactory->create();
$resource = $post->getResource();
$resource->save($post);

Deleting a model:

// Delete by ID
$post = $this->postFactory->create()->load(1);
$post->delete();

// Delete via resource
$resource = $this->postFactory->create()->getResource();
$resource->delete($post);

Bulk operations:

// Bulk save
foreach ($posts as $post) {
    $this->postRepository->save($post);
}

// Bulk delete
foreach ($postIds as $id) {
    $this->postRepository->deleteById($id);
}

Model Best Practices

Best practices for Magento model implementation.

1. Use factories, not ObjectManager:

// BAD
$post = $objectManager->create(Post::class);

// GOOD
$post = $this->postFactory->create();

2. Type-hint interfaces:

// BAD
public function save(Post $post)

// GOOD
public function save(PostInterface $post)

3. Keep models thin:

// BAD: Business logic in model
class Post extends AbstractModel
{
    public function processOrder() { /* 100 lines */ }
}

// GOOD: Delegate to service
class Post extends AbstractModel
{
    // Only data and basic operations
}

// Service class handles business logic
-class PostService
{
    public function processPost(PostInterface $post) { /* ... */ }
}

4. Use data patches for data:

// Instead of install/upgrade scripts
public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
{
    $setup->startSetup();
    
    // Create sample data
    $post = $this->postFactory->create();
    $post->setTitle('Sample Post');
    $post->save();
    
    $setup->endSetup();
}

5. Check existence before load:

$post = $this->postFactory->create()->load($id);

if (!$post->getId()) {
    throw new \Magento\Framework\Exception\NoSuchEntityException(
        __('Post with id %1 does not exist', $id)
    );
}

Quiz

1. What three components make up the Magento model architecture?

Question 1 options

2. What does _construct() do in a model?

Question 2 options

3. How should you type-hint model dependencies?

Question 3 options

4. What should models NOT contain?

Question 4 options

Flashcards

Question

What are the three model components?

Answer

Model, Resource Model, Collection

Question

What does _construct() initialize?

Answer

The resource model via $this->_init()

Question

How do you load a model?

Answer

$model->load($id) or $resource->load($model, $id)

Question

What should type-hint model dependencies?

Answer

Data interfaces (PostInterface, not Post)

Question

Where should business logic reside?

Answer

Service classes, not models

Revision Notes

Key Takeaways

  • 1. Magento models have three layers: Model, Resource Model, Collection
  • 2. _construct() initializes the resource model
  • 3. Data interfaces define API contracts for models
  • 4. Use factories for object creation, not ObjectManager
  • 5. Type-hint interfaces, not concrete classes
  • 6. Keep models thin — delegate to service classes

Interview Tips

  • Explain the three-layer model architecture
  • Describe how to create a model with data interface
  • Discuss why interfaces are preferred over concrete classes
  • Know how to load, save, and delete models

Cheat Sheet

Models Cheat Sheet

Architecture:

  • Model: Business logic + data
  • Resource Model: Database operations
  • Collection: Multiple model queries

Basic model:

class Post extends AbstractModel
{
    protected function _construct()
    {
        $this->_init(ResourceModel\Post::class);
    }
}

Load/Save/Delete:

$post->load($id);
$post->save();
$post->delete();

Type-hint: PostInterface, not Post
Create: Use factories, not ObjectManager