Hinzufügen einer neuen Methode zu einer abstrakten Klasse in Magento 2


16

Wie dieser Thread sagte: Überschreibe abstrakte Klasse in Magento 2 in Magento 1 ,

Ich kann einfach eine völlig neue Klasse erstellen. In Magento 2 müssen wir Plugins verwenden, aber Plugins erlauben mir nur, existierende Methoden zu modifizieren. Was muss ich tun, wenn ich eine neue Methode hinzufügen möchte?

Beispiel:

Diese Klasse vendor/magento/module-ui/Component/AbstractComponent.phphat ein Array von Komponenten: $componentsEs gibt keine Funktion, um Elemente für dieses Array zu entfernen / zu löschen. Wie kann ich diese Funktion erstellen?

Antworten:


0

Ich verstehe nicht, wie Sie das tun können, ohne die Klasse vollständig zu überschreiben. In Ihrem Beispiel können Sie einzelne Komponenten deaktivieren, indem Sie das Element "disabled" in der XML auf das Argument "data" setzen. Zum Beispiel:

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

Dadurch wird "title" effektiv aus dem $componentsArray entfernt.

Dies liegt an der createChildComponentMethode in der Magento\Framework\View\Element\UiComponentFactoryKlasse:

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

Dies ist nicht das, wonach ich suche ... Ich möchte einer Abstract-Klasse neue Methoden hinzufügen ... Dies ist nur ein Beispiel ... Was ist zum Beispiel, wenn ich die Elemente dynamisch entfernen möchte? In Ihrem Kommentar erwähnen Sie "komplett außer Kraft setzen", wie Sie das tun?
Matias

Anschließend müssen Sie Ihre neuen Methoden in einer Klasse definieren, die die abstrakte Klasse erweitert, und anschließend Klassen für die Unterklassen der abstrakten Klasse erstellen, die stattdessen von Ihrer Klasse erben, und die Einstellungen in di.xml festlegen. Das ist es, was ich damit meine, die Klasse vollständig zu überschreiben. Ich habe versucht, ein Beispiel zu zeigen, wie man das vermeidet.
Aaron Allen

Ja, ich verstehe Sie ... aber die Lösung ist überhaupt nicht skalierbar ... Ich kann nicht glauben, dass M2 die Möglichkeit des Überschreibens abstrakter Klassen beseitigt hat ... Ich dachte, sie würden es verbessern, anstatt es zu entfernen. .
Matias


0

Das Überladen einer Klasse in M1 im Autoloader über eine Community oder ein lokales Verzeichnis (wie in der Frage, die Sie verlinkt haben, vorgeschlagen) wurde in M1 aus sehr guten Gründen als schlechte Praxis angesehen.

Meistens verlieren Sie die Möglichkeit, Ihre Magento-Instanz zu aktualisieren, wenn die ursprüngliche Klasse an bestimmten Stellen geändert wird, was Sie in Ihrer überladenen Klasse nicht berücksichtigt haben.

Eigentlich fällt mir kein Anwendungsfall ein, in dem man einer abstrakten Klasse wirklich Methoden hinzufügen muss, da man einer eigenen Klasse immer eine eigene Logik hinzufügen und in eine Plugin / Observer / ViewModel / XML-Konfiguration integrieren kann

Der beste Weg wäre, eine neue Klasse einzuführen, die die abstrakte Klasse für Ihren speziellen Anwendungsfall erweitert, und dann Ihre Klasse bei Bedarf zu verwenden.

Wenn Sie Elemente aus einer Ui-Komponente entfernen müssen, gibt es wahrscheinlich auch eine bessere Möglichkeit, dies über das Layout / ein Plugin auf dem Layoutprozessor / durch Ändern der erforderlichen js-Datei zu tun.

Wenn Sie also Ihren speziellen Verwendungszweck beschreiben, gibt es möglicherweise eine bessere Antwort.


Ich weiß, dass das eine schlechte Praxis ist, aber zumindest haben Sie eine Möglichkeit, es zu tun. Angenommen, Sie möchten für jedes Modell, das Sie laden, einen Cache hinzufügen. Dies kann durch Ändern der Lademethode in der abstrakten Klasse geschehen. Diese Änderung wird dann an alle Klassen weitergegeben. Wenn Sie dies nicht haben, müssen Sie jedes Modell ändern, und das ist überhaupt nicht skalierbar.
Matias

Ein zweiter Anwendungsfall könnte sein, dass Sie, wenn Sie das tun möchten, was ich im Ticket sage, Elemente aus diesem Array entfernen / entfernen (als Beispiel betrachten), über alles andere nachdenken können ... Sie müssen eine neue Funktion erstellen In der abstrakten Klasse müssen Sie andernfalls in jeder erweiterten Klasse dieselbe Funktion erstellen, die wiederum überhaupt nicht skalierbar ist. Und das Schlimmste ist, dass Variablen im Magento-Kern privat sind, anstatt geschützt zu werden Die einzige Möglichkeit besteht darin, eine Methode in der abstrakten Klasse hinzuzufügen ...
Matias

Das erste Beispiel ist ganz einfach, wenn Sie dem abstrakten Modell ein Around-Plugin hinzufügen und das Ergebnis des Ladens pro Modell zwischenspeichern. Was wäre viel besser, als die abstrakte Klasse zu überladen, die jedes zukünftige Update unterbricht, bei dem das abstrakte Modell geändert wird. Sie zweites "Beispiel" Ich kann Ihnen nicht viel darüber erzählen, weil Sie im Grunde genau darum bitten, der abstrakten Klasse eine Methode hinzuzufügen, anstatt Ihren tatsächlichen Anwendungsfall
anzugeben

Übrigens ist es in Magento2 immer noch möglich, weil Sie den Composer-Autoloader manipulieren können. Es wird jedoch dringend davon abgeraten, da Sie Probleme mit Updates haben werden. magento.stackexchange.com/questions/164455/…
David Verholen

Das ist keine Option
Matias
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.