Adicionando um novo método a uma classe abstrata no Magento 2


16

Como este tópico disse: Substitua a classe abstrata no Magento 2 no Magento 1 ,

Eu posso apenas criar uma nova classe completa. No Magento 2, precisamos usar plugins, mas os plugins só me permitem modificar os métodos existentes. O que tenho que fazer se quiser adicionar um novo método?

Exemplo:

Esta classe vendor/magento/module-ui/Component/AbstractComponent.phppossui uma matriz de componentes $components:, não há função para desmarcar / excluir elementos dessa matriz. Então, como posso criar essa função?

Respostas:


0

Não vejo como você pode fazer isso sem substituir completamente a classe. No caso do seu exemplo, você pode desativar componentes individuais configurando o item "disabled" para o argumento "data" no XML. Por exemplo:

<?xml version="1.0" encoding="UTF-8"?>

<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <fieldset name="general">
        <field name="title">
            <argument name="data" xsi:type="array">
                <item name="disabled" xsi:type="boolean">true</item>
            </argument>
        </field>
    </fieldset>
</form>

Isso remove efetivamente o 'título' do $components matriz.

Isso ocorre devido ao createChildComponentmétodo na Magento\Framework\View\Element\UiComponentFactoryclasse:

 protected function createChildComponent(
        array $bundleComponents,
        ContextInterface $renderContext,
        $identifier
    ) {
        list($className, $arguments) = $this->argumentsResolver($identifier, $bundleComponents);
        if (isset($arguments['data']['disabled']) && (int)$arguments['data']['disabled']) {
            return null;
        }
        $components = [];
        foreach ($bundleComponents['children'] as $childrenIdentifier => $childrenData) {
            $children = $this->createChildComponent(
                $childrenData,
                $renderContext,
                $childrenIdentifier
            );
            $components[$childrenIdentifier] = $children;
        }
        $components = array_filter($components);
        $arguments['components'] = $components;
        if (!isset($arguments['context'])) {
            $arguments['context'] = $renderContext;
        }

        return $this->objectManager->create($className, $arguments);
    }

Não é isso que estou procurando ... Quero uma maneira de adicionar novos métodos a uma classe Abstract ... isso é apenas um exemplo ... por exemplo, e se eu quiser remover os elementos dinamicamente? No seu comentário, você menciona "substituição completa" como você faz isso?
Matias

Em seguida, você precisará definir seus novos métodos em uma classe que estenda a classe abstrata e, em seguida, criar classes para as subclasses da classe abstrata que, em vez disso, herdam de sua classe e configuram preferências em di.xml. É isso o que quero dizer com 'substituir completamente a classe'. Eu estava tentando mostrar um exemplo de como evitar isso.
Aaron Allen

Sim, eu entendo você ... mas a solução não é escalável ... Não posso acreditar que o M2 tenha removido a possibilidade de substituir as classes abstratas ... Pensei que elas o melhorariam, em vez de removê-lo .. .
Matias


0

sobrecarregar uma classe no M1 no carregador automático por meio de diretório comunitário ou local (como sugerido na pergunta que você vinculou) foi considerada uma má prática no M1 por muito boas razões.

Em geral, você perde a capacidade de atualizar sua instância do Magento se a classe original for alterada em alguns lugares, e você não considerou sua classe sobrecarregada.

Na verdade, não consigo pensar em nenhum caso de uso, onde você realmente precisa adicionar métodos a uma classe abstrata, pois você sempre pode adicionar sua própria lógica a uma classe e integrá-la em um plugin / observer / viewModel / xml config

A melhor maneira seria introduzir uma nova classe que estenda a classe abstrata para seu caso de uso específico e, em seguida, use sua classe sempre que necessário.

Se você precisar remover elementos de um componente da interface do usuário, também é provável que haja uma maneira melhor de fazê-lo via layout / um plug-in no processador de layout / alterando o arquivo js que requer isso.

Portanto, se você descrever seu caso de uso específico, poderá haver uma resposta melhor para isso.


Eu sei que isso é uma prática ruim, mas pelo menos você tem uma maneira de fazê-lo. Por exemplo, considere o caso em que você deseja adicionar um cache para cada modelo que você carrega. Isso pode ser feito modificando o método load na classe abstrata e, em seguida, essa alteração será propagada para todas as classes. Se você não tiver isso, precisará modificar cada modelo que tiver, e isso não é absolutamente escalável.
Matias

Um segundo caso de uso, pode ser, se você quiser fazer o que eu digo no ticket, desconfigurar / excluir elementos dessa matriz (considere como um exemplo), você pode pensar em qualquer outra coisa ... você precisa criar uma nova função na classe abstrata, caso contrário, você será forçado a criar a mesma função em cada classe que se estende, e isso novamente não é escalável ... E pior, porque as variáveis ​​no núcleo do Magento são privadas em vez de serem protegidas, então o única maneira de fazer isso é adicionar um método na classe abstrata ...
Matias

o primeiro exemplo é absolutamente fácil, basta adicionar um plug-in around ao modelo abstrato e armazenar em cache o resultado da carga por modelo. O que seria muito melhor do que sobrecarregar a classe abstrata que quebraria todas as atualizações futuras em que o modelo abstrato fosse alterado. Você é o segundo "exemplo" sobre o qual não posso falar muito, porque você está basicamente pedindo exatamente para adicionar um método à classe abstrata, em vez de declarar seu caso de uso real
David Verholen

btw ainda é possível no Magento2 porque você pode manipular o autoloader do compositor, mas altamente desanimado porque você terá problemas com as atualizações magento.stackexchange.com/questions/164455/…
David Verholen

Isso não é uma opção
Matias
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.