Magento 2 — Guia de sobrevivência no Front-end (Parte 2)

Lucas Calazans
10 min readJan 8, 2020

--

Magento — Guia de sobrevivência do front-end (Parte 2)

No primeiro artigo mostrei algumas questões básicas sobre os temas, se você perdeu essa parte, clique aqui para lê-lo.

O Magento 2 utiliza XML de diversas formas diferentes, disponibilizando várias configurações da loja e até mesmo configurações de classes PHP. No front-end o XML que mais utilizamos é o Layout XML, assunto esse que gera bastante dúvidas quando um desenvolvedor começa a customizar o front-end na plataforma.

Nessa segunda parte veremos as principais funcionalidades que um front-end utiliza quando se está trabalhando com Layout XML.

Qual o propósito do Layout XML?

O principal propósito desse recurso é customizar uma página específica, como a página de categoria, por exemplo. Porém, existem alguns casos em que podemos utilizá-lo para customizar diversas páginas ao mesmo tempo.

Quando estamos trabalhando com Layout XML, tratamos páginas como handles, sendo que cada página pode ter 1 ou mais handles. Abaixo vou listar os mais conhecidos:

  • default — Todas as páginas
  • cms_index_index — Home
  • catalog_category_view — Categoria
  • catalog_product_view — Produto
  • checkout_cart_index — Carrinho
  • checkout_index_index — Checkout

Cada handle desse é encarregado em customizar alguma parte da loja. Vamos pegar como exemplo o cms_index_index, este talvez seja o mais utilizado. Isso porque ele é o responsável pela página inicial (Home). Veja abaixo um simples exemplo de como adicionar um novo bloco na home utilizando esse handle.

Adicionando um bloco de exemplo na home utilizando o handle específico dessa página

No exemplo acima estou adicionando um simples texto na página inicial, não se atenha ainda para as instruções, vamos falar delas mais pra frente. Repare o nome do arquivo na barra inferior, ele é exatamente igual ao handle que comentamos, isso indica para o Magento que todo o conteúdo desse arquivo será utilizado apenas na página inicial.

Certo, mas onde podemos colocar esse arquivo?

Bom, existem alguns lugares dentro do tema em que podemos inserir novos XMLs. Repare na imagem abaixo como ficou a estrutura de pastas do tema após criar o XML acima:

Foto mostrando a estrutura de pastas do tema com o arquivo de layout
Estrutura de pastas após inserir o arquivo cms_index_index.xml

Cada handle que trabalhamos no nosso tema ficará dentro de uma pasta com o código de um módulo. No nosso exemplo foi adicionada a pasta Magento_Theme (Apesar de ter o nome Theme, este é o código de um módulo contido no core do Magento e, nesse caso, não representa o tema).

Nós podemos adicionar nossos XMLs em qualquer pasta com o código de um módulo (Magento_Theme ou Magento_Catalog por exemplo), porém, por convenção, nós adicionamos os XMLs nos módulos que são responsáveis por eles. Em outras palavras, se você estiver trabalhando com o handle checkout_index_index (Que cuida da página de Checkout) faz sentido colocá-lo na pasta Magento_Checkout. Isso irá ajudar (E muito) quando você precisar encontrar qual arquivo está criando algum bloco na página, pois você pode associar qual é o módulo responsável por ela e descartar as outras pastas.

A outra pasta necessária é a pasta layout dentro da pasta do módulo. Nessa pasta estarão todos os arquivos XMLs que esse módulo é responsável. Após isso é só criar o arquivo seguindo o padrão nome_do_handle.xml e adicionar as instruções necessárias.

Handles especiais

No exemplo acima utilizamos o cms_index_index.xml, que fica responsável apenas pela página inicial, mas e quando precisamos adicionar instruções para diversas páginas?

Para isso existem alguns handles que agem em diversas páginas ao mesmo tempo. O principal é o default (default.xml), que é o responsável por todas as páginas. Utilizamos muito esse handle para customizar o header e o footer, já que eles estão presentes na maioria das páginas.

Blocks e Containers

Certo, agora que entendemos para que servem os handles, iremos abordar as instruções que podemos utilizar dentro dos XMLs.

Até o final do artigo iremos ver as principais instruções disponíveis nos XMLs, mas a maioria delas giram em torno dos blocks e dos containers. Essas são as principais instruções que utilizaremos, as outras são utilizadas para modificar algo deles. Vamos começar pelo mais complexo que é o block.

Block

Exemplo de como utilizar um bloco

Uma página é formada por diversos blocos, então podemos dizer que um block é um pedaço de um todo. É com ele que iremos falar para o Magento renderizar um phtml (Arquivo que contém instruções php e html), sendo que esse phtml poderá chamar métodos disponíveis em uma classe PHP especificada na propriedade class (Note no código acima, estamos usando a classe Magento\...\Template).

Repare no arquivo abaixo. Este é o nosso custom.phtml que especificamos no XML acima. Falamos que o caminho do phtml é o Magento_Theme::html/custom.phtml, isso indica para o Magento que o nosso phtml estará localizado no seguinte caminho:

Dentro da pasta do tema — Magento_Theme/templates/html/custom.phtml
Caminho do custom.phtml

Nele iremos chamar um método disponível na classe Template, que é o getBaseUrl(). Esse método está disponível no phtml pois o Magento associa o arquivo de template ( phtml) com a classe PHP.

Aqui temos o nosso custom.phtml que foi definido no block

Como foi citado anteriormente, nesse arquivo nós podemos utilizar tanto HTML quanto instruções PHP. No nosso exemplo o método getBaseUrl está sendo atribuído à uma variável no começo do arquivo, que está sendo utilizada logo após, dentro de uma tag p.

Uma coisa interessante que entrou no Magento na versão 2.2 é que agora, se precisarmos criar um bloco com a classe que usamos no XML acima (A classe Template.php), não precisamos mais passar o atributo class, o Magento irá automaticamente associar essa classe ao bloco, já que essa é a classe padrão dos blocos.

Mas e se for preciso alterar um bloco que já existe?

Há também os casos em que precisamos alterar o comportamento de um bloco que já foi criado, seja um bloco criado pelo core do Magento, ou por um módulo de terceiro. Nesse caso não podemos utilizar a tag block, pois isso irá sobrescrever o bloco previamente criado.

Isso se dá porque quando o Magento encontra dois blocos com o mesmo nome, apenas o último será carregado e o anterior será descartado, técnica conhecida como override de bloco.

Para que isso não aconteça, nós usamos a tag referenceBlock. Com ela podemos informar o nome do bloco que queremos alterar, e em seguida podemos fazer nossas alterações.

Exemplo de uso do referenceBlock

Podemos fazer uma série de alterações com o referenceBlock, listei abaixo abaixo as alterações mais utilizadas.

Alterar o template do bloco:

Existem alguns casos que será necessário alterar o template de um bloco, podemos fazer isso de duas formas.

A primeira, e mais comum, é utilizando a própria tag template no referenceBlock, assim como é utilizado ao criar um bloco novo:

Alterando o template via propriedade no referenceBlock

Repare que precisamos apenas passar o nome do bloco original, em seguida passamos a propriedade template, indicando o novo template que será utilizado.

Um erro comum é quando o desenvolvedor copia todas as propriedades que existem na declaração do bloco (como a propriedade class, por exemplo) e deixa no referenceBlock. Isso não é necessário, já que o referenceBlock só precisa do name para funcionar.

A segunda forma de alterar o template é usando os arguments, tag bastante utilizada para passar parâmetros aos blocos:

Alterando o template via arguments

A ideia é a mesma da forma anterior, através da tag argument podemos alterar o template no bloco.

Porém, existe uma desvantagem em usar esse método. O Magento considera que a primeira forma (Utilizando a propriedade direto no referenceBlock) tem uma prioridade maior do que o argument. Com isso, se você estiver usando essa forma para alterar um template que foi definido através do primeiro método, a sua alteração não vai funcionar, te forçando usar via propriedade.

Adicionar novos blocos

Também é possível adicionar novos blocos usando o referenceBlock.

Adicionando blocos filhos via referenceBlock

Repare que estamos criando um novo bloco dentro do que criamos anteriormente, criando um novo nó na hierarquia do layout.

Para fazer esse novo bloco aparecer, temos que fazer uma alteração no template do bloco simple.block.example e informar onde o bloco filho deve ser renderizado. O template irá ficar assim:

Renderizando um bloco filho pelo nome

Para isso nós chamamos o método getChildHtml (Ver linha 9 acima), e passamos como parâmetro o nome do bloco que queremos que seja renderizado naquela parte do HTML, isso irá retornar o HTML processado do bloco child.block.

Há também a possibilidade de renderizar todos os blocos filhos de uma vez, caso você crie mais de um bloco, ao invés de chamar cada bloco individualmente:

Capturando todos os blocos filhos de uma vez

Repare que agora não passamos nada como parâmetro, dessa forma o Magento irá pegar todos os blocos filhos e renderizar onde antes estava renderizando apenas o bloco que passamos o nome.

Podemos fazer bastante customizações usando o referenceBlock, porém esses dois exemplos acima são os mais utilizados quando usamos essa tag.

Container

Esta é uma nova funcionalidade no Magento 2 que chegou para ajudar no agrupamento de elementos, sejam eles outros containers ou blocos.

Exemplo tirado do código do próprio Magento que mostra o uso do container na linha 11

Com o container nós podemos criar elementos HTML simples direto pelo XML, isso irá ajudar bastante quando estivermos customizando as páginas.

Repare no exemplo acima, na linha 11, temos um container sendo criado. Nele podemos passar várias informações, como o name por exemplo, que tem a mesma lógica do name dos blocos (Deve ser único e é utilizado quando queremos fazer uma alteração nele).

Há também outros atributos que são específicos dos containers, como o htmlTag, htmlClass e o htmlId. A ideia de cada um é bem clara:

  • htmlTag: Atributo responsável por falar qual será a tag que o container irá utilizar para ser renderizado no HTML final.
  • htmlClass: Nesse atributo nós podemos passar a classe CSS que será inserida na tag do container (Se quiser passar mais de uma, deve-se usar espaço entre as classes).
  • htmlId: Aqui nós podemos definir um id para essa tag, este irá ser renderizado como um atributo no HTML.

referenceContainer

Talvez seja mais comum o uso do referenceContainer se comparado ao container em si. Isso porque os layouts base do Magento são criados basicamente via containers, com isso os elementos que utilizamos para inserir nossos blocos já foram criados previamente e precisamos utilizar o referenceContainer, veja abaixo um exemplo:

Conteúdo do arquivo 1column.xml, template base do Magento 2

Esse é um dos layouts base que estão disponíveis no Magento 2, repare que só temos containers sendo criados. Com isso, nós temos que utilizar o referenceContainer para que possamos adicionar um novo bloco (Ou um outro container) em um desses pontos.

Se quisermos adicionar um novo bloco no header.container ficaria assim:

Adicionando um novo bloco dentro de um container que já existe

Repare que não precisamos colocar na mesma estrutura em que o header.container foi criado (Dentro do container page.wrapper). Quando estamos utilizando tanto o referenceContainer, quanto o referenceBlock, só precisamos colocar dentro do body que o Magento conseguirá encontrar o elemento que informamos.

Certo, o que mais podemos fazer?

Como foi dito no começo, os blocos e os containers são os principais itens no Layout XML, porém temos outras ações que podemos fazer em nossas customizações:

before/after

O before e o after são atributos muito úteis no XML. Com eles podemos informar onde exatamente ficará o nosso bloco/container, se será antes ou depois de determinado elemento, ou até mesmo antes ou depois de todos os elementos.

Vamos rever o nosso primeiro exemplo desse artigo:

Exemplo de uso do before

Repare que no final da linha 6, estamos utilizando o before="-", isso irá indicar que o nosso bloco simple.text.example será inserido dentro do container content antes de todos os outros elementos. Sempre que passamos um hífen no before ou no after, estamos falando que queremos esse elemento antes ou depois de todos os outros elementos que estão no elemento pai (Nesse caso o content).

Exemplo de uso do after passando um elemento específico

Também podemos informar o nome de um elemento no before/after. No exemplo acima, estamos criando um novo bloco (Dentro do mesmo elemento que criamos o bloco antes — content) e informamos que este será inserido depois do bloco simple.text.example.

move

E se quisermos mudar a posição de um bloco que já existe?

Uso do move para alterar o posicionamento do bloco de copyright

No exemplo acima estamos mudando o posicionamento do bloco de copyright, que originalmente fica dentro do container com nome footer, para o elemento footer-container.

Para o move funcionar precisamos passar, no mínimo, 2 informações. A primeira é o element, que recebe o nome do elemento que será alterado (Pode ser tanto um bloco como um container) e em seguida precisamos informar o destination, que é o elemento que receberá o bloco/container.

remove

Podemos também remover blocos/containers de uma página de uma forma bem simples.

Exemplo de uso do remove

Nesse caso estamos removendo o container header.container numa página, para isso basta usar o referenceContainer (Ou o referenceBlock caso seja um bloco), passar o nome do container e usar o remove="true".

Conclusão

Essa parte do Magento pode ser bem complexa para quem está começando (E até mesmo para quem já tem experiência com Magento) e é bem extensa também. Esse é o básico sobre Layout XML, ainda conseguimos fazer outras coisas nessa parte do Magento, mas com esse conhecimento já conseguimos fazer a maioria das customizações necessárias.

Vou deixar na parte de referências abaixo alguns links do devdocs (Documentação oficial do Magento 2) para um conhecimento mais aprofundado.

--

--

Lucas Calazans
Lucas Calazans

Responses (2)