Dodanie nowej metody do klasy abstrakcyjnej w Magento 2


16

Jak powiedział ten wątek: Zastąp klasę abstrakcyjną w Magento 2 w Magento 1 ,

Mogę po prostu stworzyć zupełnie nową klasę. W Magento 2 musimy używać wtyczek, ale wtyczki pozwalają mi tylko modyfikować istniejące metody. Co muszę zrobić, jeśli chcę dodać nową metodę?

Przykład:

Ta klasa vendor/magento/module-ui/Component/AbstractComponent.phpma tablicę komponentów: $componentsnie ma funkcji do rozbrojenia / usunięcia elementów dla tej tablicy. Jak mogę utworzyć tę funkcję?

Odpowiedzi:


0

Nie rozumiem, jak możesz to zrobić bez całkowitego przesłonięcia klasy. W naszym przykładzie możesz wyłączyć poszczególne komponenty, ustawiając element „disabled” na argument „data” w pliku XML. Na przykład:

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

To skutecznie usuwa „tytuł” ​​z $componentstablicy.

Wynika to z createChildComponentmetody w Magento\Framework\View\Element\UiComponentFactoryklasie:

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

Nie tego szukam ... Chcę sposobu, aby dodać nowe metody do klasy Abstract ... to tylko przykład ... na przykład, co jeśli chcę dynamicznie usuwać elementy? W swoim komentarzu wspominasz o „całkowitym zastąpieniu”, jak to zrobić?
Matias

Następnie musisz zdefiniować nowe metody w klasie, która rozszerza klasę abstrakcyjną, a następnie utworzyć klasy dla podklas klasy abstrakcyjnej, które zamiast tego dziedziczą po twojej klasie i ustawić preferencje w pliku di.xml. To mam na myśli przez „całkowite zastąpienie klasy”. Próbowałem pokazać przykład, jak tego uniknąć.
Aaron Allen

Tak, rozumiem cię ... ale rozwiązanie wcale nie jest skalowalne ... Nie mogę uwierzyć, że M2 usunęło możliwość zastąpienia klas abstrakcyjnych ... Myślałem, że zamierzają to ulepszyć, zamiast go usunąć ... ,
Matias


0

przeciążanie klasy w M1 w autoloaderze przez społeczność lub katalog lokalny (jak sugerowano w pytaniu, które podłączyłeś) zostało uznane za złą praktykę w M1 z bardzo dobrych powodów.

Przeważnie tracisz możliwość ulepszenia instancji Magento, jeśli oryginalna klasa zostanie zmieniona miejscami, czego nie rozważałeś w swojej przeciążonej klasie.

Właściwie nie mogę wymyślić żadnego przypadku użycia, w którym naprawdę musisz dodać metody do klasy abstrakcyjnej, ponieważ zawsze możesz dodać własną logikę do własnej klasy i zintegrować ją z konfiguracją plugin / observer / viewModel / xml

Najlepszym sposobem byłoby wprowadzenie nowej klasy rozszerzającej klasę abstrakcyjną dla konkretnego przypadku użycia, a następnie użycie klasy w razie potrzeby.

Jeśli musisz usunąć elementy ze składnika interfejsu użytkownika, istnieje również lepszy sposób, aby to zrobić za pomocą układu / wtyczki procesora układu / zmiany wymaganego pliku js.

Jeśli więc opisujesz swój konkretny przypadek użycia, może być na to lepsza odpowiedź.


Wiem, że robienie tego jest złą praktyką, ale przynajmniej masz jeden sposób, aby to zrobić. Na przykład rozważmy przypadek, w którym chcesz dodać pamięć podręczną dla każdego ładowanego modelu. Można to zrobić, modyfikując metodę ładowania w klasie abstrakcyjnej, a następnie ta zmiana zostanie propagowana do wszystkich klas. Jeśli go nie masz, musisz zmodyfikować każdy posiadany model, a to absolutnie nie jest skalowalne.
Matias

Drugi przypadek użycia może być taki, że jeśli chcesz zrobić to, co mówię w bilecie, odłączyć / usunąć elementy z tej tablicy (rozważ jako przykład), możesz pomyśleć o czymkolwiek innym ... potrzebujesz stworzyć nową funkcję w klasie abstrakcyjnej, w przeciwnym razie będziesz zmuszony utworzyć tę samą funkcję w każdej klasie, która się rozszerza, i to znowu nie jest w ogóle skalowalne ... A najgorsze, ponieważ zmienne w rdzeniu Magento są prywatne zamiast chronione, więc jedynym sposobem na to jest dodanie metody do klasy abstrakcyjnej ...
Matias

pierwszy przykład jest absolutnie łatwy, po prostu dodając wtyczkę wokół modelu abstrakcyjnego i buforując wynik obciążenia według modelu. Co byłoby znacznie lepsze niż przeciążenie klasy abstrakcyjnej, która zepsułaby każdą przyszłą aktualizację, w której model abstrakcyjny zostałby zmieniony. Drugi „przykład” nie mogę ci wiele powiedzieć, ponieważ w zasadzie pytasz dokładnie o dodanie metody do klasy abstrakcyjnej, zamiast
podawać

btw wciąż jest możliwe w Magento2, ponieważ możesz manipulować autoloaderem kompozytora, ale bardzo odradzam, ponieważ będziesz miał problemy z aktualizacjami magento.stackexchange.com/questions/164455/…
David Verholen

To nie jest opcja
Matias
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.