Agregar un nuevo método a una clase abstracta en Magento 2


16

Como dijo este hilo: Anular la clase abstracta en Magento 2 en Magento 1 ,

Solo puedo crear una clase completamente nueva. En Magento 2, necesitamos usar complementos, pero los complementos solo me permiten modificar los métodos existentes. ¿Qué debo hacer si quiero agregar un nuevo método?

Ejemplo:

Esta clase vendor/magento/module-ui/Component/AbstractComponent.phptiene una matriz de componentes: $componentsno hay función para desarmar / eliminar elementos para esa matriz. Entonces, ¿cómo puedo crear esa función?

Respuestas:


0

No veo cómo puedes hacer eso sin anular completamente la clase. En el caso de su ejemplo, puede deshabilitar componentes individuales configurando el elemento "deshabilitado" en el argumento "datos" en el XML. Por ejemplo:

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

Esto elimina efectivamente el "título" de la $componentsmatriz.

Esto se debe al createChildComponentmétodo en la Magento\Framework\View\Element\UiComponentFactoryclase:

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

Esto no es lo que estoy buscando ... Quiero una forma de agregar nuevos métodos a una clase abstracta ... esto es solo un ejemplo ... por ejemplo, ¿qué pasa si quiero eliminar los elementos dinámicamente? En tu comentario mencionas "anulación completa" ¿cómo haces eso?
Matias

Luego, deberá definir sus nuevos métodos en una clase que extienda la clase abstracta y luego crear clases para las subclases de la clase abstracta que, en su lugar, heredarán de su clase y establecerán preferencias en di.xml. Eso es lo que quiero decir con "anular completamente la clase". Estaba tratando de mostrar un ejemplo de cómo evitar hacer eso.
Aaron Allen el

Sí, te entiendo ... pero la solución no es escalable en absoluto ... No puedo creer que M2 haya eliminado la posibilidad de anular las clases abstractas ... Pensé que iban a mejorarlo, en lugar de eliminarlo ... .
Matias


0

sobrecargar una clase en M1 en el cargador automático a través de un directorio local o comunitario (como se sugiere en la pregunta que ha vinculado) se consideró una mala práctica en M1 por muy buenas razones.

En su mayoría, pierde la capacidad de actualizar su instancia de Magento si la clase original se cambia en algunos lugares, que no consideró en su clase sobrecargada.

En realidad, no puedo pensar en ningún caso de uso, en el que realmente necesite agregar métodos a una clase abstracta, ya que siempre puede agregar su propia lógica a una clase propia e integrarla en una configuración de complemento / observador / viewModel / xml

La mejor manera sería, introduciendo una nueva clase que extienda la clase abstracta para su caso de uso específico y luego use su clase donde sea necesario.

Si necesita eliminar elementos de un componente Ui, también es probable que haya una mejor manera de hacerlo a través del diseño / un complemento en el procesador de diseño / cambiando el archivo js que lo requiere.

Entonces, si describe su caso de uso específico, podría haber una mejor respuesta a esto.


Sé que hacerlo es una mala práctica, pero al menos, tienes una forma de hacerlo. Por ejemplo, considere el caso en que desea agregar un caché para cada modelo que cargue. Esto podría hacerse modificando el método de carga en la clase abstracta y luego este cambio se propagará a todas las clases. Si no tiene esto, debe modificar cada modelo que tenga, y eso no es escalable en absoluto.
Matias

Un segundo caso de uso, podría ser si desea hacer lo que digo en el ticket, desarmar / eliminar elementos de esa matriz (considere como un ejemplo), puede pensar en cualquier otra cosa ... necesita crear una nueva función en la clase abstracta, de lo contrario, se verá obligado a crear la misma función en cada clase que se extienda, y eso nuevamente no es escalable en absoluto ... Y lo peor, porque las variables en el núcleo de Magento son privadas en lugar de estar protegidas, por lo que la única forma de hacerlo es agregar un método en la clase abstracta ...
Matias

El primer ejemplo es absolutamente fácil simplemente agregando un complemento de entorno al modelo abstracto y almacenando en caché el resultado de la carga por modelo. Lo cual sería mucho mejor que sobrecargar la clase abstracta que rompería cada actualización futura en la que se cambie el modelo abstracto. Segundo "ejemplo" sobre el que no puedo decir mucho, porque básicamente está pidiendo exactamente agregar un método a la clase abstracta, en lugar de indicar su caso de uso real
David Verholen

por cierto, todavía es posible en Magento2 porque puedes manipular el autocargador de compositores, pero muy desalentado porque tendrás problemas con las actualizaciones magento.stackexchange.com/questions/164455/…
David Verholen

Esa no es una opción
Matias
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.