Como criar um ViewModel no Magento 2
Tags: php, magento2, tutorial, braziliandevs
Published: 2021-12-01 14:08:27

## Camada de Visualização no Magento 2

### O que é um bloco no Magento 2?

O Magento trabalha com o padrão MVC para o desenvolvimento de seus módulos, a *View* (camada de visualização) é contituída por três camadas: *layout*, *Block* e *template*.

A visualizaço do conteúdo em uma página é constituída de duas partes, a parte "visual" que são os *templates* (arquivos em phtml) e a parte lógica que são os arquivos dentro do diretório *Block* (arquivos em PHP). Devem ser utilizados em locais para que não ocorra repetição de conteúdo e/ou código em outras páginas, contêiners e/ou blocos. É possível utiliza o *Block* (parte lógica) em outros *templates* (parte visual), e é possível reutilizar um *template* em outros contêiners e páginas.

---

## Código para inserir um bloco

### Layout

Para inserir, remover ou editar algum bloco na página deve ser editado ou criado um arquivo de layout. Saiba como criar um arquivo de *layout* neste *post* "[Como criar arquivos de layout Magento 2](https://dev.to/santanaluc94/como-criar-arquivos-de-layout-magento-2-1i69)".

```xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <referenceContainer name="content">
        <block name="{block_name}" template="{Vendor_Module}::{path}/{file_name}.phtml">
            <arguments>
                <argument name="{view_model_name}" xsi:type="object">{Vendor}\{Module}\ViewModel\{ClassName}</argument>
            </arguments>
        </block>
    </referenceContainer>
</page>
```

### ViewModel

Um arquivo de *ViewModel* é uma abstração da camada de visualização que expõe propriedades e comandos públicos. A *ViewModel* permite que os desenvolvedores separem as funcionalidades e lógicas de negócio das classes do tipo *Block* em classes separadas que são mais fáceis de manter, testar e reutilizar.

Este tipo de recurso está disponível a partir da versão 2.2 do Magento. Para utilizar as *ViewModels* é necessário passar o caminho da classe *ViewModel* como um argumento para o bloco utilizado nos arquivos de *layout*. Nos *templates* só é possível acessar a métodos públicos das ViewModels. Este tipo de arquivo deve seguir a estruturas de pastas `\{Vendor}\{Module}\{Block}\{ClassName}.php`. Cada arquivo de *ViewModel* deve implementar a classe `\Magento\Framework\View\Element\Block\ArgumentInterface`.

```php
<?php

namespace {Vendor}\{Module}\ViewModel;

use Magento\Framework\View\Element\Block\ArgumentInterface;

class {ClassName} implements ArgumentInterface
{
    public function {methodName}(): {type}
    {
        // Code here
    }
}
```

Pode ser inserida classes através de injeção de dependêcia para conseguir exibir os dados necessários no *template*.

> Caso o *template* não necessite de lógica, é recomendado não deixar o atributo `class` no arquivo de layout ou criar um bloco e apenas extender a classe `\Magento\Framework\View\Element\Template`, sem inserir nenhum método.
> 

---

### Templates

Saiba mais sobre arquivos de *templates* no *post* "[Como criar um bloco no Magento 2](https://dev.to/santanaluc94/como-criar-um-bloco-no-magento-2-25fh)".

No arquivo de *template* podemos usar a variável `$block` com o método `getData('{view_model_name}')` para acessar o argumento do arquivo *layout*, que retornará a classe *ViewModel*. E através do retorno dessa classe, teremos o acesso aos métodos da classe *ViewModel*.

```php
<?php
/**
 * @var \{Vendor}\{Module}\Block\{BlockName} $block
 * @var \{Vendor}\{Module}\ViewModel\{ClassName} $viewModel
 */

$viewModel = $block->getData('{view_model_name}');
$viewModel->{methodName}();
?>
```

---

## Finalização

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

### Habilitando as alterações

Apague os arquivos que são gerados na compilação do Magento e execute o comando PHP para gerar a configuração das injeções de dependência e todas as classes ausentes que precisam ser geradas (*proxys*, *interceptors*, etc) e para limpar todos os caches de armazenamento em cache do processos.

```bash
rm -rf var/generation/
rm -rf generated/
php bin/magento setup:di:compile
php bin/magento cache:clean
php bin/magento flush
```

### Diretórios e Arquivos

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

```
- app/
  - code/
    - {Vendor}/
      - {Module}/
        - etc/
          - module.xml
        - view/
          - {area}/
            - layout/
              - {router_id}_{controller_directory}_{controller_name}.xml
            - templates/
              - {paths}/
                - {file_name}.phtml
        - ViewModel/
          - {ClassName}.php
        - registration.php
        - composer.json
```