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