Como criar plugins no Magento 2

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

Contextualizando

Um plugin, ou interceptor, é uma classe que modifica o comportamento de funções públicas de outras classes, interceptando uma chamada de função. Isso permite estender ou substituir o comportamento de métodos públicos originais para qualquer classe ou interface.

Essa abordagem de interceptação reduz conflitos entre extensões que alteram o comportamento da mesma classe ou método. A implementação da classe do tipo plugin altera o comportamento de uma função da classe especificada no di.xml, mas não altera a classe em si. O Magento chama os interceptors sequencialmente de acordo com a ordem de classificação, então não podem ter conflitos uns com os outros.


Código para criar plugin

di.xml

O primeiro argumento para os métodos before, after e around é o objeto que fornece o acesso a todos os métodos públicos da classe do método observado. Estes tipo de funcionalidade deve ser implementada dentro do arquivo di.xml, seguindo a estruturas de pastas \{Vendor}\{Module}\etc\{area}\di.xml. Já os arquivos com a lógica que serão executados devem seguir a estrutura de pastas \{Vendor}\{Module}\Plugin\{PluginName} e não devem estender nenhuma classe, apenas conter o nome do método que será adicionado a funcionalidade com o sufixo necessário.

Parâmetros obrigatórios para a declaração de um plugin:

  • Type name: uma classe ou interface que o plugin irá observar
  • Plugin name: um nome que identifica o plugin. Também utilizado para mesclar configurações do plugin.
  • Plugin type: nome da classe do plugin ou nome do tipo virtual.

Parâmetros não obrigatórios para a declaração de um plugin:

  • Plugin sort order: plugins que chamam o mesmo método seguem a ordem crescente desse atributo
  • Plugin disabled: para desabilitar um plugin, deve definir esse atributo como true. O valor padrão é false
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="{Vendor}\{Module}\{Directory}\{ClassName}">
        <plugin name="{plugin_name}" type="{Vendor}\{Module}\Plugin\{PluginName}" disabled="false" sortOrder="10" />
    </type>
</config>
Enter fullscreen mode Exit fullscreen mode

Before

O Magento executa todos os métodos before antes da chamada para o método observado.

É possível utilizar métodos before para alterar argumentos de um método observado, retornando um argumento modificado. Se existirem muitos argumentos, o método deve retornar um array com todos os argumentos. Se o método não alterar o argumento do método observado, ele deverá retornar null.

<?php

namespace {Vendor}\{Module}\Plugin;

use {Vendor}\{Module}\{Directory}\{ClassName};

class {PluginName}
{
    public function before{MethodName}({ClassName} $subject): void
    {
        // Code here
    }
}
Enter fullscreen mode Exit fullscreen mode

After

O Magento executa todos os métodos after após a conclusão da execução do método observado. Esse tipo de método é obrigatório ter um retorno. É possível utilizar métodos after para alterar o resultado de um método observado. modificando o resultado original e retornando o valor alterado no final do método.

Os métodos after possuem acesso a todos os argumentos do método observado. Quando o método observado termina sua execução, o Magento passa o resultado e os argumentos para o método after seguinte (caso exista mais de um método after para o mesmo método observado). Se o método observado não possui retorno (void), então o método after deverá retornar null.

Os métodos after não precisam declarar todos os argumentos do método observado, exceto o argumento que o método do plugin irá utilizar e todos os seus anteriores (os posteriores não são necessários).

<?php

namespace {Vendor}\{Module}\Plugin;

use {Vendor}\{Module}\{Directory}\{ClassName};

class {PluginName}
{
    public function after{MethodName}({ClassName} $subject): {type}
    {
        // Code here
    }
}
Enter fullscreen mode Exit fullscreen mode

Around

Evite usar plugins com métodos around quando eles não forem necessários, pois eles aumentam a stack trace e afetam a performance.

Antes da lista de argumentos do método observado, métodos around recebe um callable que permitirá a chamada do próximo método da cadeia. Quando o método executar o callable, o Magento chama o próximo plugin ou a função observada.

Se o método around não chamar o callable, ele prevenirá a execução de todos os seguintes plugins da cadeia e o método observado.

Quando o método around envolve um método observado que possui argumentos, o método around deve aceitar esses argumentos e encaminhá-los ao invocar a chamada do proceed. Deve-se ter cuidado ao combinar os parâmetros padrões e seus type hints da assinatura do método observado.

Caso o método observado possua argumentos com valores padrões, devem ser inseridos os mesmos valores padrões dos argumentos no método around.

<?php

namespace {Vendor}\{Module}\Plugin;

use {Vendor}\{Module}\{Directory}\{ClassName};

class {PluginName}
{
    public function around{MethodName}(
        {ClassName} $subject,
        callable $proceed
    ): {type} {
        // Code before here
        $proceed();
        // Code after here
    }
}
Enter fullscreen mode Exit fullscreen mode

Finalizando

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
Enter fullscreen mode Exit fullscreen mode

Diretórios e Arquivos

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

- app/
  - code/
    - {Vendor}/
        - {Module}/
          - etc/
            - di.xml
            - module.xml
          - Plugin/
            - {PluginName}.php
          - registration.php
          - composer.json
Enter fullscreen mode Exit fullscreen mode
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .