Como criar um ViewModel no Magento 2

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".

<?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

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".

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
/**
 * @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.

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

37