Como criar Model, Resource Model e Collection no Magento 2
Tags: php, magento2, braziliandevs, tutorial
Published: 2021-10-11 12:32:43

# Contextualizando

### O que é ORM?

**ORM** (*Object-Relational Mapping*) é uma técnica de mapeamento de objeto-relacional que visa criar uma camada de mapeamento entre o modelo de objetos da aplicação para o modelo relacional do banco de dados, de forma a abstrair o acesso ao mesmo, ou seja, é uma técnica de mapeamento entre um modelo de dados relacional e um modelo orientado a objetos que geralmente é a biblioteca ou *framework* que ajuda no mapeamento e uso do banco de dados. a ORM visa resolver, ou pelo menos minimizar, as diferenças entres estes dois modelos.

A ORM é uma biblioteca que é escrita para encapsular o código necessário para manipular os dados, para que não seja necessário utilizar o SQL no código da programação orientada a objetos.

O Magento 2 não tem todos os recursos normalmente oferecidos por uma ORM, ele possui apenas uma abstração sobre consultas por linhas do SQL (Resource Model).

### Quando usar as classes Model, Resource Model e Collection?

As classes de *Model*, *Resource* *Model* e *Collection* estendem classes que fazem o mapeamento entre a abstração da entidade e o modelo relacional do banco de dados.

Estas classes servem para o gerenciamento de dados em uma tabela personalizada, ou seja, as classes são para operações de dados no modelo CRUD (*Create*, *Read*, *Update* e *Delete*) de uma única tabela. Saiba como criar uma tabela personalizada no post "[Como criar tabelas personalizadas no banco de dados com db_schema.xml no Magento 2]([https://dev.to/santanaluc94/como-criar-tabelas-personalizadas-no-banco-de-dados-com-dbschema-xml-35b9-temp-slug-4930189?preview=b86aa52030edf18c80d01c5e3fec599d89dbcddcb8818d2ba8d8b9e7fa5e2ed13e7945657c416f4cbcbc0b7d6ab38f0ad6b5a6ad8420cee22eb34349](https://dev.to/santanaluc94/como-criar-tabelas-personalizadas-no-banco-de-dados-com-dbschema-xml-35b9-temp-slug-4930189?preview=b86aa52030edf18c80d01c5e3fec599d89dbcddcb8818d2ba8d8b9e7fa5e2ed13e7945657c416f4cbcbc0b7d6ab38f0ad6b5a6ad8420cee22eb34349))".

---

# Código para a criação da Model, Resource Model e Collection

### Model

A classes *Model* é responsável por diversas funções, como as regras de negócio de uma aplicação, encapsular dados do seu negócio, acessar, extrair e manipular dados das entidades. O termo *Model* vêm do padrão de arquitetura MVC (*Model-Controller-View*).

A classe *Model* deve seguir a estrutura de pastas `\{Vendor}\{Module}\Model\{ModelName}` e deve estender a classe `\Magento\Framework\Model\AbstractModel`, que necessita que a classe a implemente o método `_construct()`. A classe *Model* herdará a classe `\Magento\Framework\DataObject` para seus objetos.

```php
<?php

namespace {Vendor}\{Module}\Model;

use Magento\Framework\Model\AbstractModel;
use Magento\Framework\Model\Context;
use Magento\Framework\Registry;
use {Vendor}\{Module}\Model\ResourceModel\{ResourceModelName};

class {ModelName} extends AbstractModel
{
    protected $_cacheTag = '{table_name}';
    protected $_eventPrefix = '{table_name}';

    public function __construct(
        Context $context,
        Registry $registry
    ) {
        parent::__construct($context, $registry);
    }

    protected function _construct(): void
    {
        $this->_init({ResourceModelName}::class);
    }
}
```

- `$_cacheTag`: um identificador único para uso de cache;
- `$_eventPrefix`: um prefixo para eventos a serem disparados;

Caso a classe de modelo esteja tratando de uma entidade, é recomendado utilizar a seguinte interface `\Magento\Framework\DataObject\IdentityInterface` ou implementar uma interface personalizada da sua entidade com todos os métodos requisitados da entidade em questão.

### Resource Model

A classe *Resource Model* é responsável pela execução de todas as operações no banco de dados, além de mapear uma entidade em uma tabela. Esta classe executa todas as operações de CRUD e é responsável pela lógica de negócio.

A classe *Resource Model* deve seguir a estrutura de pastas `\{Vendor}\{Module}\Model\ResourceModel\{ResourceModelName}` e deve estender a classe abstrata `\Magento\Framework\Model\ResourceModel\Db\AbstractDb`, que contém os métodos para buscar informações do banco de dados e requisita a implementação do método `_construct()`.

```php
<?php

namespace {Vendor}\{Module}\Model\ResourceModel;

use Magento\Framework\Model\ResourceModel\Db\AbstractDb;
use Magento\Framework\Model\ResourceModel\Db\Context;

class {ResourceModelName} extends AbstractDb
{
    public function __construct(
        Context $context
    ) {
        parent::__construct($context);
    }

    protected function _construct(): void
    {
        $this->_init('{table_name}', '{entity_column_id}');
    }
}
```

### Collection

A classe *Collection* é considerada a *Resource Model* que permite filtrar e buscar os dados de uma tabela de uma coleção da entidade, ou seja, uma coleção de objetos que possibilita o filtro, agrupamento, ordenação e carregamento de uma determinada entidade, *array* ou a própria coleção.

A classe *Collection* deve seguir a estrutura de pastas `\{Vendor}\{Module}\Model\ResourceModel\{EntityName}\{CollectionName}` e deve estender a classe abstrata `\Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection`, que contém os métodos para tratar dos dados da coleção da entidade e requisita a implementação do método `_construct()`. A classe *Collection* instanciará a classe `\Magento\Framework\Data\Collection` para seus objetos de retorno da entidade.

É possível unir dados de outras tabelas em uma *Collection* com o `join()` para serem executados no banco de dados.

```php
<?php

namespace {Vendor}\{Module}\Model\ResourceModel\{EntityName};

use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;
use Magento\Framework\Data\Collection\EntityFactoryInterface;
use Psr\Log\LoggerInterface;
use Magento\Framework\Data\Collection\Db\FetchStrategyInterface;
use Magento\Framework\Event\ManagerInterface;
use Magento\Framework\DB\Adapter\AdapterInterface;
use Magento\Framework\Model\ResourceModel\Db\AbstractDb;
use {Vendor}\{Module}\Model\{ModelName};
use {Vendor}\{Module}\Model\ResourceModel\{ResourceModelName};

class {CollectionName} extends AbstractCollection
{
    protected $_idFieldName = '{entity_column_id}';
    protected $_eventPrefix = '{table_name}_collection';
    protected $_eventObject = '{table_name}_collection';

    public function __construct(
        EntityFactoryInterface $entityFactory,
        LoggerInterface $logger,
        FetchStrategyInterface $fetchStrategy,
        ManagerInterface $eventManager,
        AdapterInterface $connection = null,
        AbstractDb $resource = null
    ) {
        parent::__construct(
            $entityFactory,
            $logger,
            $fetchStrategy,
            $eventManager,
            $connection,
            $resource
        );
    }

    protected function _construct(): void
    {
        $this->_init(
            {ModelName}::class,
            {ResourceModelName}::class
        );
    }
}
```

- `$_idFieldName`: campo identificador para a coleção de itens;
- `$_eventPrefix`: nome do prefixo do evento que são disparados pela *Model*;
- `$_eventObject`: nome do parâmetro do evento.

---

# Finalizando

> Valores entre chaves (`{test}`) devem ser alterados na implementação do código.

## Habilitando o alterações

Gera a configuração das injeções de dependência e todas as classes ausentes.

```bash
# Gera a configuração das injeções de dependência e todas as classes ausentes.
php bin/magento setup:di:compile

# Limpa o armazenamento (cache) de todos os processos do Magento
php bin/magento cache:flush
```

## Diretórios e Arquivos

Segue a a lista de diretórios e arquivos que devem ser criados.

```
- app/
  - code/
    - {Vendor}/
        - {Module}/
          - etc/
            - db_schema.xml
            - module.xml
          - Model/
            - {EntityName}.php
            - ResourceModel/
              - {EntityName}.php
              - {EntityName}/
                - Collection.php
          - registration.php
          - composer.json
```