Criando um Módulo para M2

Escrito por Mario SAM

Nosso objetivo aqui é simples, mostrar os passos necessários para criar um módulo para o M2. Obviamente será algo simples, pois o foco está no processo de criação do módulo, e não nas suas funcionalidades, teorias ou conceitos.

O resultado final e o código pronto para download você encontra em Microsoft Clarity Módulo Grátis para M2.

Passo 1 – Estrutura de Diretórios

Na sua instalação, você vai encontrar o diretório “app/code“, dentro dele você vai criar um diretório com o nome da sua Empresa, e dentro da pasta “Empresa” outro diretório com nome do seu módulo, neste exemplo vamos criar um módulo chamado “Clarity“.

app/code/MarioSAM/Clarity

Passo 2 – Os Arquivos Necessários

Basicamente para ter um módulo, 3 arquivos são essenciais: composer.json, registration.php e o module.xml. Todos os demais arquivos que você vier a criar, dependem do tipo de módulo que você quer criar e das boas práticas de desenvolvimento que você aplicar.

app/code/MarioSAM/Clarity/composer.json

{
    "name": "mariosam/module-clarity",
    "version": "1.0.0",
    "description": "Module to insert clarity analytics.",
    "type": "magento2-module",
    "license": "OSL-3.0",
    "authors": [
        {
            "email": "eu@mariosam.com.br",
            "name": "MarioSAM"
        }
    ],
    "minimum-stability": "dev",
    "require": {},
    "autoload": {
        "files": [
            "registration.php"
        ],
        "psr-4": {
            "MarioSAM\\Clarity\\": ""
        }
    }
}

Você provavelmente reparou que este arquivo faz referência ao próximo arquivo que devemos criar:

app/code/MarioSAM/Clarity/registration.php

<?php
use Magento\Framework\Component\ComponentRegistrar;

ComponentRegistrar::register(ComponentRegistrar::MODULE, 'MarioSAM_Clarity', __DIR__);

Estes dois vão servir basicamente para instalar ou atualizar seu módulo, a base mesmo vem agora:

app/code/MarioSAM/Clarity/etc/module.xml

<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="MarioSAM_Clarity" setup_version="1.0.0" />
</config>

Passo 3 – Instalando seu módulo

Agora você precisa avisar ao seu sistema de cor Magenta, que estes novos arquivos precisam ser carregados e inicializados como módulos. Para isso abra um Terminal (prompt de comando), e navegue até o diretório de instalação da sua loja (neste exemplo será: magento2).

Caso você não esteja familiarizado, “MacBookPro-MarioSAM:” é o nome da minha máquina, “magento2” é meu diretório de instalação do sistema, e “mariosam$” é o prompt de comando com nome do usuário logado.

O primeiro e principal comando que iremos executar (e que vai carregar seu composer.json) será:

bin/magento module:enable MarioSAM_Clarity

Como você pode observar, o comando é bem simples, e diz: Amigo! Habilite meu módulo, o nome dele é esse aí. Na sequência, é interessante e recomendável rodar outro comando:

bin/magento setup:upgrade

Esse comando atualiza o sistema com as novas informações, principalmente quando seu módulo faz inserções no banco de dados, cria tabelas, sobrescreve classes, ou mesmo, está atualizando a versão do seu módulo. E por fim, rode:

bin/magento cache:clean

Apenas para garantir que você vai enxergar as atualizações que foram feitas, para que não fique nada desatualizado em cache.

Pronto! Temos um módulo que não faz absolutamente nada!

Passo 4 – Planejando nosso XML

Vamos criar agora mais 3 arquivos dentro do diretório “etc” que irão moldar a maneira como nosso módulo é acessado no Admin. Isso significa que nem todos os módulos que você encontrar por aí terão estes arquivos. Você pode inclusive deixar de criar alguns deles, e mesmo assim este módulo continuará funcionando.

app/code/MarioSAM/Clarity/etc/config.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
    <default>
        <clarity>
            <configurations>
                <enabled>0</enabled>
                <track_code></track_code>
            </configurations>
        </clarity>
    </default>
</config>

No config.xml você inicializa as variáveis do seu módulo. Alguns destes valores podem ficar oculto para o usuário (se você desejar), e servem de referência base para não bugar seu código.

app/code/MarioSAM/Clarity/etc/acl.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Acl/etc/acl.xsd">
    <acl>
        <resources>
            <resource id="Magento_Backend::admin">
                <resource id="Magento_Backend::stores">
                    <resource id="Magento_Backend::stores_settings">
                        <resource id="Magento_Config::config">
                            <resource id="MarioSAM_Clarity::module_clarity_config" title="Clarity Settings"/>
                        </resource>
                    </resource>
                </resource>
            </resource>
        </resources>
    </acl>
</config>

Vejo muita gente ignorando esse arquivo acl.xml (access control level), talvez por não entenderem do que se trata. No entanto, é uma boa prática incluir este arquivo, pois permite que o cliente possa configurar o nível de permissão de uso do seu módulo.

app/code/MarioSAM/Clarity/etc/adminhtml/system.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
    <system>
        <!-- Tab is the menu option at left [MARIOSAM] -->
        <tab id="mariosam" translate="label" sortOrder="250">
            <label>Mario SAM</label>
        </tab>
        <!-- Section is a sub-menu option inside Tab. -->
        <section id="clarity" translate="label" sortOrder="1000" showInDefault="1" showInWebsite="1" showInStore="1">
            <class>separator-top</class>
            <label>Clarity Settings</label>
            <tab>mariosam</tab>
            <!-- resource is to ACL -->
            <resource>MarioSAM_Clarity::module_clarity_config</resource>
            <!-- Group is the box at right with your config options. -->
            <group id="configurations" translate="label" type="text" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="1">
                <label>Clarity Configuration</label>
                <comment><![CDATA[How to use Clarity? Access the Mario SAM blog and read the post.]]></comment>
                <!-- Turn On or Turn off this module -->
                <field id="enabled" translate="label" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
                    <label>Module Enable</label>
                    <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
                </field>
                <!-- Set the tracking code for your clarity account -->
                <field id="track_code" translate="label" type="text" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1">
                    <label>Your code ID</label>
                    <comment>ex.: 3xkyqgjd4r</comment>
                </field>
            </group>
        </section>
    </system>
</config>

Teríamos muita coisa para falar a respeito deste arquivo system.xml, pois é ele quem dá vida as telas de configuração do seu módulo no admin da sua loja.

Passo 5 – Preparando o resultado final

Na etapa anterior a gente fez os ajustes de como o módulo deveria aparecer no Admin da loja, agora vamos planejar seu aspecto final, o resultado esperado. Que neste exemplo, será incluir um código javascript em todas as páginas da loja (dentro do tema vigente).

app/code/MarioSAM/Clarity/view/frontend/layout/default.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">
    <body>
        <!-- soon as the page start to loading -->
        <referenceContainer name="after.body.start">
            <block name="input.code" as="input_code" template="MarioSAM_Clarity::inputCode.phtml" ifconfig="clarity/configurations/enabled">
                <arguments>
                    <argument name="view_model" xsi:type="object">MarioSAM\Clarity\ViewModel\ClarityViewModel</argument>
                </arguments>
            </block>
        </referenceContainer>
    </body>
</page>

Temos outro xml para informar que em todas as páginas do tema (default.xml) este novo bloco de conteúdo deve ser carregado. Podemos observar que ele carrega um arquivo PHTML, e conecta uma classe ViewModel à este arquivo.

app/code/MarioSAM/Clarity/view/frontend/templates/inputCode.phtml

<?php
/** @var $viewModel MarioSAM\Clarity\ViewModel\ClarityViewModel */
$viewModel = $block->getViewModel();

/** inicializando model e variaveis */
if ( $viewModel->getEnabled() ) {
    $_idTrack = $viewModel->getTrackingId();
?>

<script type="text/javascript">
//<![CDATA[
$(document).ready(function () {
    (function(c,l,a,r,i,t,y){
        c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
        t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
        y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
    })(window, document, "clarity", "script", "<?php echo $_idTrack; ?>");
//]]>
</script>
<?php } /* if modulo esta ativo */ ?>

O arquivo inputCode.phtml seria o destino final de toda nossa jornada, onde o resultado de todo processo será apresentado. Nesse caso, recuperamos alguns valores da instância ViewModel (que conectamos no XML) e inserimos dentro do código javascript que foi incorporado.

Passo 6 – Conectando o Frontend ao Backend

Na etapa anterior a gente criou um arquivo XML que se conecta a um objeto do tipo ViewModel (poderia ser um Block também). Este arquivo tem por objetivo ler as configurações criadas lá no admin, tratar alguns dados se necessário, e preparar o retorno para ser apresentado no frontend (no phtml).

app/code/MarioSAM/Clarity/ViewModel/ClarityViewModel.php

<?php
namespace MarioSAM\Clarity\ViewModel;

class ClarityViewModel implements \Magento\Framework\View\Element\Block\ArgumentInterface
{
    protected $_scopeConfig;

    /**
     * ConsentPopupViewModel constructor.
     *
     */
    public function __construct(
        \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
        \Magento\Framework\View\Element\Template\Context $context
    )
    {
        $this->_scopeConfig = $scopeConfig;

        //parent::__construct($context);
    }

    /**
     * Inform if this module is set up to enable or disable.
     * 
     * @return boolean
     */
    public function getEnabled()
    {
        return $this->_scopeConfig->getValue('clarity/configurations/enabled', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
    }

    /**
     * Get the clarity ID informed in admin page.
     * 
     * @return text
     */
    public function getTrackingId()
    {
        return $this->_scopeConfig->getValue('clarity/configurations/track_code', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
    }
}

Deixamos o código bem simples aqui. Além do construtor da classe, temos apenas dois métodos que serão carregados no phtml. Um para verificar se o módulo está ativo e dessa forma a página deve ser carregada. E outro para recuperar o valor do Tracking Code ID configurado.

Rode o comando de cache:clean novamente, atualize seu frontend, e veja o resultado. Dependendo do código que você adicionou ao seu módulo, talvez seja necessário rodar o comando setup:upgrade também.

Passo 7 – Internacionalizando

Imagino que você queira seguir as boas práticas de desenvolvimento, e disponibilizar seu módulo para o maior número de pessoas possível. Nesse caso, vamos criar agora os arquivos de tradução do seu módulo.

app/code/MarioSAM/Clarity/i18n/en_US.csv

"Clarity Configuration","Clarity Configuration"
"Clarity Settings","Clarity Settings"
"Enable","Enable"
"ex.: 3xkyqgjd4r","ex.: 3xkyqgjd4r"
"How to use Clarity? Access the Mario SAM blog and read the post.","How to use? Access the <a href='https://en.mariosam.eu' target='_blank'>Mario SAM</a> blog and read the post."
"Mario SAM","Mario SAM"
"Module Enable","Module Enable"
"No","No"
"Yes","Yes"
"Your code ID","Your code ID"

Arquivo de tradução é algo bem simples, do lado esquerdo vai a chave (a mesma utilizada no código/phtml/classes), e do lado direito o valor apresentado na renderização da página. Por padrão (boas práticas) crie sempre um arquivo en_US.csv. Abaixo vamos criar agora a versão em português.

app/code/MarioSAM/Clarity/i18n/pt_BR.csv

"Clarity Configuration","Clarity Configuração"
"Clarity Settings","Clarity Microsoft"
"Enable","Habilitar"
"ex.: 3xkyqgjd4r","ex.: 3xkyqgjd4r"
"How to use Clarity? Access the Mario SAM blog and read the post.","Como usar? Acesse o blog <a href='https://mariosam.com.br' target='_blank'>Mario SAM</a> e leia o artigo."
"Mario SAM","Mario SAM"
"Module Enable","Habilitar Módulo"
"No","Não"
"Yes","Sim"
"Your code ID","Código ID"

Você pode repetir o processo para todos os outros idiomas que desejar. Para ver o resultado, não esqueça de atualizar o cache.

Acabou?

Mais simples que isso, acredito que, só se fizessemos o clássico Hello World! Foram 7 passos para mostrar que desenvolver um módulo para a cor Magenta não é nenhum bicho de 7 cabeças. No fim, nossa estrutura ficou assim:

E o resultado pode ser visto no código HTML gerado no frontend:

Quer aprender mais sobre desenvolvimento de módulos para esta incrível plataforma? Recomendo Magento 2 O Curso.

Sucesso!

O Autor

Mario SAM

Desenvolvedor Magento com certificação M1 Developer e M1 FrontEnd Developer. Graduado em Web Design e Programação, pós-graduado em Gestão de Projetos e TI. Não sou matemático mas estou aqui para somar.