Como criar uma configuração personalizada no Magento 2

Lucas Teixeira dos Santos Santana - Oct 5 '21 - - Dev Community

Contextualizando

O que é uma configuração?

Configurações no Magento 2 são campos que pertencem a seções e grupos de configurações, onde podem conter valores pré-configurados, textos e/ou números para que os fluxos, lógicas e definições das lojas sigam esses valores, que são salvos na tabela core_config_data.

Vários módulos podem declarar arquivos de configuração que afetam o mesmo tipo de configuração, e esses vários arquivos de configuração são unificados na mesma página. Os nós nos arquivos de configuração são mesclados com base em seus XPaths, que possuem um atributo especial definido na idAttributes declarada como seu identificador. Este identificador deve ser exclusivo para todos os nós aninhados no mesmo nó pai.

Se os identificadores de nó forem iguais (ou se não houver nenhum identificador definido), todo o conteúdo subjacente no nó (atributos, nós filhos e conteúdo) será substituído. Se os identificadores de nó não forem iguais, o nó é um novo filho do nó pai.

Por que fazer uma configuração personalizada?

É recomendada a criação de configurações personalizadas para personalizar aspectos específicos do comportamento do seu módulo, podendo ser habilitar/desabilitar funcionalidades, tipos de clientes que podem acessar a determinada funcionalidade, textos que serão apresentados, valores para determinado cálculo, países atendidos por determinado serviço, entre outros inúmeros motivos.


Código para criação de uma configuração personalizada

system.xml

Para o gerenciamento de configurações no Magento é necessário criar um arquivo chamado system.xml que deve seguir a estrutura de pasta \{Vendor}\{Module}\etc\adminhtml\system.xml. Este arquivo é dividido em 4 partes: tab, section, group e field.

Com o arquivo system.xml é possível criar novas configurações como estender configurações existentes, apenas recriando a estrutura desejada.

As configurações do Magento 2 são encontradas em Painel administrativo → Store → Settings → Configuration. O nó <tab> é uma guia utilizada para dividir diferentes áreas de configuração semanticamente. Cada <tab> pode conter uma ou mais <section>, que podem ser referenciadas como submenu.

<?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 id="{tab_id}" translate="label" class="{css_class_name}" sortOrder="{sort_number}">
            <label>{Text to translate}</label>
        </tab>

        <section id="{section_id}" showInDefault="{1/0}" showInWebsite="{1/0}" showInStore="{1/0}" sortOrder="{sort_number}" translate="label">
            <label>{Text to translate}</label>
            <tab>{tab_id}</tab>
            <resource>{Vendor}_{Module}::{acl_path}</resource>
            <frontend_model>{Vendor}\{Module}\{Directory}\{ClassName}</frontend_model>
            <include path="{Vendor}_{Module}::{path_name}/{file_name}.xml"/>

            <group id="{group_id}" translate="label comment" sortOrder="{sort_number}" showInDefault="{1/0}" showInWebsite="{1/0}" showInStore="{1/0}" canRestore="{1/0}">
                <label>{Text to translate}</label>
                <fieldset_css>{css_class_name}</fieldset_css>
                <frontend_model>{Vendor}\{Module}\{Directory}\{ClassName}</frontend_model>
                <clone_model>{Vendor}\{Module}\{Directory}\{ClassName}</clone_model>
                <clone_fields>{1/0}</clone_fields>
                <comment>{Comment to translate}</comment>
                <hide_in_single_store_mode>{1/0}</hide_in_single_store_mode>

                <group id="{child_group_id}" sortOrder="{sort_number}">
                </group>
                <depends>
                    <field id="{section_id}/{group_id}/{field_id}">{1/0}</field>
                </depends>
                <include path="{Vendor}_{Module}::{path_name}/{file_name}.xml"/>

                <field id="{field_tag_chilren_id}" translate="label" type="text">
                    <label>{Field label}</label>
                    <comment>{Field comment}</comment>
                    <tooltip>{Field tooltip}</tooltip>
                    <hint>{Field hint}</hint>
                    <frontend_class>{Vendor}\{Module}\{Directory}\{ClassName}</frontend_class>
                    <frontend_model>{Vendor}\{Module}\{Directory}\{ClassName}</frontend_model>
                    <backend_model>{Vendor}\{Module}\{Directory}\{ClassName}</backend_model>
                    <source_model>{Vendor}\{Module}\{Directory}\{ClassName}</source_model>
                    <config_path>{new_section_id}/{new_group_id}/{new_field_id}</config_path>
                    <validate>{validation-rules}</validate>
                    <can_be_empty>{1/0}</can_be_empty>
                    <if_module_enabled>{1/0}</if_module_enabled>
                    <base_url type="media" scope_info="1">{frontend_name}/{controller_directory}/{controller_name}</base_url>
                    <upload_dir config="{section_id}/{group_id}/{field_id}" scope_info="1">{frontend_name}/{controller_directory}/{controller_name}</upload_dir>
                    <button_label>{Button label}</button_label>
                </field>

                <field id="{field_text_id}" translate="label" type="text">
                    <label>{Text to translate}</label>
                </field>

                <field id="{field_textarea_id}" translate="label" type="textarea">
                    <label>{Text to translate}</label>
                </field>

                <field id="{field_select_id}" translate="label" type="select">
                    <label>{Text to translate}</label>
                    <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
                </field>

                <field id="{field_multiselect_id}" translate="label" type="multiselect">
                    <label>{Text to translate}</label>
                    <source_model>{Vendor}\{Module}\Model\{Directory}\{ClassName}</source_model>
                </field>

                <field id="{field_obscure_id}" translate="label" type="obscure">
                    <label>{Text to translate}</label>
                    <backend_model>Magento\Config\Model\Config\Backend\Encrypted</backend_model>
                </field>

                <field id="{field_password_id}" translate="label" type="password">
                    <label>{Text to translate}</label>
                </field>

                <field id="{field_label_id}" translate="label" type="label">
                    <label>{Text to translate}</label>
                    <frontend_model>{Vendor}\{Module}\{Directory}\{ClassName}</frontend_model>
                </field>

                <field id="{field_time_id}" translate="label" type="time">
                    <label>{Text to translate}</label>
                </field>

                <field id="{field_allowspecific_id}" translate="label" type="allowspecific">
                    <label>{Text to translate}</label>
                    <source_model>{Vendor}\{Module}\Model\{Directory}\{ClassName}</source_model>
                </field>

                <field id="{field_image_id}" translate="label" type="image">
                    <backend_model>Magento\Config\Model\Config\Backend\Image</backend_model>
                    <upload_dir config="{section_id}/{group_id}/{field_id}" scope_info="1">{frontend_name}/{controller_directory}/{controller_name}</upload_dir>
                    <base_url type="media" scope_info="1">{frontend_name}/{controller_directory}/{controller_name}</base_url>
                </field>
            </group>
        </section>
    </system>
</config>
Enter fullscreen mode Exit fullscreen mode

config.xml

Cada campo no arquivo system.xml não terá nenhum valor salvo na tabela core_config_data a princípio, o retorno do valor do campo será null. Então, para definir um valor inicial para o campo, é necessário criar um arquivo chamado config.xml que deve seguir a estrutura de pasta \{Vendor}\{Module}\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>
        <{section_id}>
            <{group_id}>
                <{field_id}>{value}</{field_id}>
            </{group_id}>
        </{section_id}>
    </default>
</config>
Enter fullscreen mode Exit fullscreen mode

Acessando as os valores

Para acessar o valor de uma configuração salva no banco, basta injetar a classe \Magento\Framework\App\Config\ScopeConfigInterface e acessar o método getValue(string $path, \Magento\Store\Model\ScopeInterface::SCOPE_STORE, $scopeCode = null) ou o método isSetFlag(string $path, \Magento\Store\Model\ScopeInterface::SCOPE_STORE, $scopeCode = null), passando o caminho do campo desejado e o ID do escopo da loja desejada.

<?php

namespace {Vendor}\{Module}\Model\Config\Source;

use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Store\Model\ScopeInterface;

class {ClassName}
{
    private const CUSTOM_MODULE_PATH_CONFIG = '{section_id}/{group_id}/{field_id}';

    public function __construct(
        private ScopeConfigInterface $scopeConfig
    ) {
    }

    public function getConfigValue(?int $storeId = null): string|int|bool
    {
        return $this->scopeConfig->getValue(
            self::CUSTOM_MODULE_PATH_CONFIG,
            ScopeInterface::SCOPE_STORE,
            $storeId
        );
    }

    public function isConfigEnable(?int $storeId = null): bool
    {
        return $this->scopeConfig->isSetFlag(
            self::CUSTOM_MODULE_PATH_CONFIG,
            ScopeInterface::SCOPE_STORE,
            $storeId
        );
    }
}
Enter fullscreen mode Exit fullscreen mode

Finalizando

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

Diretórios e Arquivos

Segue a a lista de diretórios e arquivos a serem criados.

- app/
  - code/
    - {Vendor}/
      - {Module}/
        - etc/
          - adminhtml/
            - system.xml
          - config.xml
          - module.xml
          - Model/
            - Config/
              - Source/
                - {ClassName}.php
        - registration.php
        - composer.json
Enter fullscreen mode Exit fullscreen mode

Atributos e nós

Para formar as configurações com exatidão segue as tabelas dos atributos e nós do arquivo system.xml:

Atributos de Tab

Atributos Descrição Tipo Obrigatório
id Define o identificador que é utilizado na guia. typeId sim
translate Define o campo que deve ser traduzido. o nó filho <label> que será traduzido. O valor deve ser o nome da tag que será traduzido, então deve ser label. string opcional
type Define o tipo de entrada do elemento HTML renderizado. O valor padrão é text. string opcional
sortOrder Define a ordem de classificação da guia. A ordem é determinada por números crescente, então números menores aparecerão primeiro. float opcional
class Adicionar uma classe CSS definida para renderizar junto com o elemento HTM da <tab> string opcional

Nós filhos de Tab

Descrição Tipo
label Define a legenda do nó que será exibido. string

Atributos de Section

Atributos Descrição Tipo Obrigatório
id Define o identificador que é utilizado na seção. typeId sim
translate Define o campo que deve ser traduzido. o nó filho <label> que será traduzido. O valor deve ser o nome da tag que será traduzido, então deve ser label. string opcional
type Define o tipo de entrada do elemento HTML renderizado. O valor padrão é text. string opcional
sortOrder Define a ordem de classificação da seção. A ordem é determinada por números crescente, então números menores aparecerão primeiro. float opcional
showInDefault Define se a seção será exibida nas configurações de escopo. O valor 1 exibirá a configuração e o valor 0 não exibirá. integer opcional
showInStore Define se a seção será exibida nos níveis da loja. O valor 1 exibirá a configuração e o valor 0 não exibirá. integer opcional
showInWebsite Define se a seção será exibida nos níveis dos sites da loja. O valor 1 exibirá a configuração e o valor 0 não exibirá. integer opcional
canRestore Define se a seção pode ser restaurada ao valor padrão. integer opcional
advanced Atributo depreciado. boolean opcional
extends Ao fornecer um identificador de outra seção, o conteúdo deste nó estenderá a seção referenciada. string opcional

Nós filhos de Section

Descrição Tipo
label Define a legenda do nó que será exibido. string
class Adicionar uma classe CSS definida para renderizar junto com o elemento HTM da <section>. string
tab Referenciar seção a uma <tab>. O valor deve ser o atributo id do nó <tab>. typeTabId
resource Referenciar seção a um recurso ACL para fornecer permissões das configurações. typeAclResourceId
group Define um ou mais grupos ou subgrupos. typeGroup
frontend_model Especifica um Model para alterar a renderização da saída. typeModel
include Utilizado para incluir arquivos adicionais compatíveis com system_include.xsd. Normalmente, utilizado para estruturar grandes arquivos system.xml includeType

Atributos de Group

Atributos Descrição Tipo Obrigatório
id Define o identificador que é utilizado na seção. typeId sim
translate Define o campo que deve ser traduzido. o nó filho <label> que será traduzido. O valor deve ser o nome da tag que será traduzido, então deve ser label. string opcional
type Define o tipo de entrada do elemento HTML renderizado. O valor padrão é text. string opcional
sortOrder Define a ordem de classificação da seção. A ordem é determinada por números crescente, então números menores aparecerão primeiro. float opcional
showInDefault Define se a seção será exibida nas configurações de escopo. O valor 1 exibirá a configuração e o valor 0 não exibirá. integer opcional
showInStore Define se a seção será exibida nos níveis da loja. O valor 1 exibirá a configuração e o valor 0 não exibirá. integer opcional
showInWebsite Define se a seção será exibida nos níveis dos sites da loja. O valor 1 exibirá a configuração e o valor 0 não exibirá. integer opcional
canRestore Define se a seção pode ser restaurada ao valor padrão. integer opcional
extends Ao fornecer um identificador de outra seção, o conteúdo deste nó estenderá a seção referenciada. string opcional

Nós filhos de Group

Descrição Tipo
label Define a legenda do nó que será exibido. string
fieldset_css Adiciona um ou mais classes CSS a um grupo de campos. string
frontend_model Especifica um Model para alterar a renderização da saída. typeModel
clone_model Especifica um determinado Model para clonar os campos. typeModel
clone_fields Habilita ou Desabilita campos clonados. integer
comment Adiciona um comentário abaixo do grupo. Pode ser utilizado conteúdo HTML através do nó <![CDATA[//]]>. string
hide_in_single_store_mode Se o grupo deve estar visível no modo de uma única visão da loja. O valor 1 exibirá a configuração e o valor 0 não exibirá. integer
field Define um ou mais campos que devem estar disponíveis dentro do grupo. field
group Define um ou mais grupos ou subgrupos. group
depends Pode ser utilizado para declarar dependências de outros campos. É utilizado para exibir campos/grupos específicos quando um determinado campo tem o valor 1. Espera um nó <field id="{section_id}/{group_id}/{field_id}>{1/0}</field>. field
attribute Atributo personalizado que pode ser utilizado na classe Model para alteração do frontend. Normalmente é utilizada para deixar a classe mais dinâmica. attribute
include Utilizado para incluir arquivos adicionais compatíveis com system_include.xsd. Normalmente, utilizado para estruturar grandes arquivos system.xml. includeType

Atributos de field

Atributos Descrição Tipo Obrigatório
advanced Atributo depreciado. boolean opcional
id Define o identificador que é utilizado no grupo. typeId sim
translate Define o campo que deve ser traduzido. o nó filho <label> que será traduzido. O valor deve ser o nome da tag que será traduzido, então deve ser label. string opcional
type Define o tipo de entrada do elemento HTML renderizado. O valor padrão é text. string opcional
sortOrder Define a ordem de classificação dos campos. A ordem é determinada por números crescente, então números menores aparecerão primeiro. float opcional
showInDefault Define se o campo será exibido nas configurações de escopo. O valor 1 exibirá a configuração e o valor 0 não exibirá. integer opcional
showInStore Define se o campo será exibido nos níveis da loja. O valor 1 exibirá a configuração e o valor 0 não exibirá. integer opcional
showInWebsite Define se o campo será exibido nos níveis dos sites da loja. O valor 1 exibirá a configuração e o valor 0 não exibirá. integer opcional
canRestore Define se o grupo pode ser restaurado ao valor padrão. integer opcional
extends Ao fornecer um identificador de outro campo, o conteúdo deste nó estenderá ao campo referenciado. string opcional

Tipos de Field

Descrição
text Valor padrão, única linha de texto para o campo.
textarea Bloco de texto.
select Dropdown, podendo ter um source_model. Também utilizado para seleções Yes/No, utilizando a classe \Magento\Search\Model\Adminhtml\System\Config\Source\Engine.
multiselect Similar ao tipo select, mas podendo ter múltiplas seleções.
button Um botão que dispara um evento imediato. Requer um Model personalizado para definir a ação do botão.
obscure Um campo de texto com o valor encriptado e exibe *****. Caso o campo seja alterado por inspeção de elementos no navegador não exibirá o valor real.
password Similar ao tipo obscure exceto o valor neste campo não é encriptado. Caso o campo seja alterado por inspeção de elementos no navegador exibirá o valor real.
file Permite o upload de um arquivo no processo.
label Define uma legenda ao invés de um campo editável. Usando este tipo quando um campo for editável apenas em escopos específicos.
time Controle para definir o tempo usando três menus (hora, minuto e segundo).
allowspecific Uma lista para múltiplas seleções de países. Requer um source_model.
image Permite o upload de imagens.
note Permite que uma note informativa seja adicionada a página. Este tipo requer um frontend_model para renderizar.

Nós filhos de Field

Descrição Tipo
label Define a legenda do nó que será exibido. string
comment Adiciona um comentário abaixo do campo. Pode ser utilizado conteúdo HTML através do nó <![CDATA[//]]>. string
tooltip Outro elemento possível do frontend que também podem ser utilizado para descrever o significado deste campo. Será exibido como um pequeno ícone ao lado do campo. string
hint Exibe informações adicionais. Disponíveis somente com o atributo frontend_model. string
frontend_class Adicionar uma classe CSS definida para renderizar junto com o elemento HTM da <field>. string
frontend_model Especifica um Model para alterar a renderização e modificar a saída no frontend. typeModel
backend_model Especifica um Model para modificar os valores configurados no backend. typeModel
source_model Especifica um Model que fornece uma específica configuração de valores na fonte. typeModel
config_path Pode ser utilizado para substituir o caminho de configuração genérica de um campo. typeConfigPath
validate Define diferentes regras de validações (separadas por vírgulas). string
can_be_empty Utilizado quando o type é do tipo multiselect para especificar que o campo pode ser vazio. integer
if_module_enabled Utilizado para exibir um campo somente quando o módulo estiver habilitado. typeModel
base_url Utilizado na combinação com o nó upload_dir para o upload de arquivos. typeUrl
upload_dir Especifica o diretório para upload. Esse nó contem atributos e nós adicionais. typeUploadDir
button_url Exibe um botão se o nó button_label for especificado. Normalmente são utilizados na combinação com um Model para o frontend. typeUrl
button_label Exibe um botão se o nó button_url for especificado. Normalmente são utilizados na combinação com um Model para o frontend. string
hide_in_single_store_mode Se o campo deve estar visível no modo de uma única visão da loja. O valor 1 exibirá a configuração e o valor 0 não exibirá. integer
source_service Serviço utilizado para popular opções do tipo select. complexType
depends Pode ser utilizado para declarar dependências de outros campos. É utilizado para exibir campos/grupos específicos quando um determinado campo tem o valor 1. Espera um nó <field id="{section_id}/{group_id}/{field_id}>{1/0}</field>. complexType
attribute Atributo personalizado que pode ser utilizado na classe Model para alteração do frontend. Normalmente é utilizada para deixar a classe mais dinâmica. complexType

Validação dos campos

Descrição
alphanumeric Permite letras, números, espaços ou sublinhados.
integer Permite números inteiros positivos e negativos.
ipv4 Permite um endereço de IP v4 válido.
ipv6 Permite um endereço de IP v6 válido.
letters-only Permite apenas letras (maiúsculas e minúsculas).
letters-with-basic-punc Permite letras ou pontuações. Deve passar na expressão regular /^[a-z\-.,()\u0027\u0022\s]+$/i.
mobileUK Permite tipos de telefone celulares no formato britânico (UK).
no-marginal-whitespace Não permite espaços em branco no início ou fim do valor.
no-whitespace Não permite espaços em branco.
phoneUK Permite tipos de telefone no formato britânico (UK).
phoneUS Permite tipos de telefone no formato estado-unidense (US).
required-entry Não permite um valor vazio (equivalente ao validate_no_empty).
time Permite um tempo válido no formato de 24 horas, entre 00:00:00 e 23:59:59.
time12h Permite um tempo válido no formato de 12 horas, entre 00:00:00 am e 12:59:59 pm.
validate-admin-password Permite 7 caracteres ou mais, usando numéricos e alfabéticos.
validate-alphanum-with-spaces Permite o uso de letras, números ou espaços.
validate-clean-url Permite um endereço de URL válido.
validate-currency-dollar Permite o valor válido de uma quantia em dólar.
validate-data Permite o uso de letras, número e underlines. A primeira letra deve conter uma letra como caractere (deve passar na expressão regular /^[A-Za-z]+[A-Za-z0-9_]+$/).
validate-date-au Permite o formato de data dd/mm/yyyy.
validate-email Permite um endereço de e-mail válido.
validate-emailSender Permite um endereço de e-mail válido.
validate-fax Permite um número de fax válido.
validate-no-empty Não permite um valor vazio (equivalente ao required-entry).
validate-no-html-tags Não permite o uso de HTML no valor.
validate-password Permite 6 caracteres ou mais, usando numéricos e alfabéticos. Espaços no início e ao fim serão ignorados.
validate-phoneLax Permite um número de telefone válido no formato (000) 000-0000 ou 000-000-0000.
validate-phoneStrict Permite um número de telefone válido no formato (000) 000-0000 ou 000-000-0000.
validate-select Força que a opção da seleção tenha um valor escolhido, não podendo ser null, 0 ou ''.
validate-ssn Permite um número de seguro social válido estado-unidense (US).
validate-street Permite o uso de letras, números, espaços e o caractere #.
validate-url Permite um endereço de URL válido. Requer o protocolo (http://, https:// ou ftp://).
validate-xml-identifier Permite um identificador CML válido.
validate-zip-us Permite um código postal válido no formato estado-unidense (US).
binUS Permite o valor do número de identificação do veículo no formato estado-unidense (US).
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .